Skip to content

Commit 310a488

Browse files
committed
Allocate one vec per row, not cell
1 parent ad69145 commit 310a488

File tree

3 files changed

+93
-46
lines changed

3 files changed

+93
-46
lines changed

src/lib.rs

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ use std::collections::{VecDeque, HashMap};
8585
use std::fmt;
8686
use std::io;
8787
use std::mem;
88+
use std::ops::Range;
8889
use std::result;
8990
use std::sync::Arc;
9091
use std::time::Duration;
@@ -488,7 +489,9 @@ impl InnerConnection {
488489
Ok((param_types, columns))
489490
}
490491

491-
fn read_rows(&mut self, buf: &mut VecDeque<Vec<Option<Vec<u8>>>>) -> Result<bool> {
492+
fn read_rows<F>(&mut self, mut consumer: F) -> Result<bool>
493+
where F: FnMut(RowData)
494+
{
492495
let more_rows;
493496
loop {
494497
match try!(self.read_message()) {
@@ -502,8 +505,12 @@ impl InnerConnection {
502505
break;
503506
}
504507
backend::Message::DataRow(body) => {
505-
let row = try!(body.values().map(|v| v.map(ToOwned::to_owned)).collect());
506-
buf.push_back(row);
508+
let mut row = RowData::new();
509+
let mut it = body.values();
510+
while let Some(value) = try!(it.next()) {
511+
row.push(value);
512+
}
513+
consumer(row);
507514
}
508515
backend::Message::ErrorResponse(body) => {
509516
try!(self.wait_for_ready());
@@ -694,12 +701,11 @@ impl InnerConnection {
694701
fn read_type(&mut self, oid: Oid) -> Result<Other> {
695702
try!(self.setup_typeinfo_query());
696703
try!(self.raw_execute(TYPEINFO_QUERY, "", 0, &[Type::Oid], &[&oid]));
697-
let mut rows = VecDeque::new();
698-
try!(self.read_rows(&mut rows));
699-
let row = rows.pop_front();
704+
let mut row = None;
705+
try!(self.read_rows(|r| row = Some(r)));
700706

701707
let get_raw = |i: usize| {
702-
row.as_ref().and_then(|r| r.get(i)).and_then(|r| r.as_ref().map(|r| &**r))
708+
row.as_ref().and_then(|r| r.get(i))
703709
};
704710

705711
let (name, type_, elem_oid, rngsubtype, basetype, schema, relid) = {
@@ -770,14 +776,13 @@ impl InnerConnection {
770776
fn read_enum_variants(&mut self, oid: Oid) -> Result<Vec<String>> {
771777
try!(self.setup_typeinfo_enum_query());
772778
try!(self.raw_execute(TYPEINFO_ENUM_QUERY, "", 0, &[Type::Oid], &[&oid]));
773-
let mut rows = VecDeque::new();
774-
try!(self.read_rows(&mut rows));
779+
let mut rows = vec![];
780+
try!(self.read_rows(|row| rows.push(row)));
775781

776782
let ctx = SessionInfo::new(&self.parameters);
777783
let mut variants = vec![];
778784
for row in rows {
779-
let raw = row.get(0).and_then(|r| r.as_ref().map(|r| &**r));
780-
variants.push(try!(String::from_sql_nullable(&Type::Name, raw, &ctx)
785+
variants.push(try!(String::from_sql_nullable(&Type::Name, row.get(0), &ctx)
781786
.map_err(Error::Conversion)));
782787
}
783788

@@ -804,17 +809,16 @@ impl InnerConnection {
804809
fn read_composite_fields(&mut self, relid: Oid) -> Result<Vec<Field>> {
805810
try!(self.setup_typeinfo_composite_query());
806811
try!(self.raw_execute(TYPEINFO_COMPOSITE_QUERY, "", 0, &[Type::Oid], &[&relid]));
807-
let mut rows = VecDeque::new();
808-
try!(self.read_rows(&mut rows));
812+
let mut rows = vec![];
813+
try!(self.read_rows(|row| rows.push(row)));
809814

810815
let mut fields = vec![];
811816
for row in rows {
812817
let (name, type_) = {
813-
let get_raw = |i: usize| row.get(i).and_then(|r| r.as_ref().map(|r| &**r));
814818
let ctx = SessionInfo::new(&self.parameters);
815-
let name = try!(String::from_sql_nullable(&Type::Name, get_raw(0), &ctx)
819+
let name = try!(String::from_sql_nullable(&Type::Name, row.get(0), &ctx)
816820
.map_err(Error::Conversion));
817-
let type_ = try!(Oid::from_sql_nullable(&Type::Oid, get_raw(1), &ctx)
821+
let type_ = try!(Oid::from_sql_nullable(&Type::Oid, row.get(1), &ctx)
818822
.map_err(Error::Conversion));
819823
(name, type_)
820824
};
@@ -1329,6 +1333,43 @@ impl<'a> GenericConnection for Transaction<'a> {
13291333
}
13301334
}
13311335

1336+
struct RowData {
1337+
buf: Vec<u8>,
1338+
indices: Vec<Option<Range<usize>>>,
1339+
}
1340+
1341+
impl RowData {
1342+
fn new() -> RowData {
1343+
RowData {
1344+
buf: vec![],
1345+
indices: vec![],
1346+
}
1347+
}
1348+
1349+
fn push(&mut self, cell: Option<&[u8]>) {
1350+
let index = match cell {
1351+
Some(cell) => {
1352+
let base = self.buf.len();
1353+
self.buf.extend_from_slice(cell);
1354+
Some(base..self.buf.len())
1355+
}
1356+
None => None,
1357+
};
1358+
self.indices.push(index);
1359+
}
1360+
1361+
fn len(&self) -> usize {
1362+
self.indices.len()
1363+
}
1364+
1365+
fn get(&self, index: usize) -> Option<&[u8]> {
1366+
match &self.indices[index] {
1367+
&Some(ref range) => Some(&self.buf[range.clone()]),
1368+
&None => None,
1369+
}
1370+
}
1371+
}
1372+
13321373
trait OtherNew {
13331374
fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Other;
13341375
}
@@ -1340,13 +1381,13 @@ trait DbErrorNew {
13401381
}
13411382

13421383
trait RowsNew<'a> {
1343-
fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a>;
1344-
fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a>;
1384+
fn new(stmt: &'a Statement<'a>, data: Vec<RowData>) -> Rows<'a>;
1385+
fn new_owned(stmt: Statement<'a>, data: Vec<RowData>) -> Rows<'a>;
13451386
}
13461387

13471388
trait LazyRowsNew<'trans, 'stmt> {
13481389
fn new(stmt: &'stmt Statement<'stmt>,
1349-
data: VecDeque<Vec<Option<Vec<u8>>>>,
1390+
data: VecDeque<RowData>,
13501391
name: String,
13511392
row_limit: i32,
13521393
more_rows: bool,

src/rows.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
use fallible_iterator::FallibleIterator;
44
use postgres_protocol::message::frontend;
55
use std::ascii::AsciiExt;
6-
use std::borrow::Cow;
76
use std::collections::VecDeque;
87
use std::fmt;
98
use std::io;
109
use std::ops::Deref;
1110
use std::slice;
1211

13-
use {Result, SessionInfoNew, RowsNew, LazyRowsNew, StatementInternals, WrongTypeNew};
12+
use {Result, SessionInfoNew, RowsNew, LazyRowsNew, StatementInternals, WrongTypeNew, RowData};
1413
use transaction::Transaction;
1514
use types::{FromSql, SessionInfo, WrongType};
1615
use stmt::{Statement, Column};
@@ -35,18 +34,18 @@ impl<'a, T> Deref for MaybeOwned<'a, T> {
3534
/// The resulting rows of a query.
3635
pub struct Rows<'stmt> {
3736
stmt: MaybeOwned<'stmt, Statement<'stmt>>,
38-
data: Vec<Vec<Option<Vec<u8>>>>,
37+
data: Vec<RowData>,
3938
}
4039

4140
impl<'a> RowsNew<'a> for Rows<'a> {
42-
fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
41+
fn new(stmt: &'a Statement<'a>, data: Vec<RowData>) -> Rows<'a> {
4342
Rows {
4443
stmt: MaybeOwned::Borrowed(stmt),
4544
data: data,
4645
}
4746
}
4847

49-
fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
48+
fn new_owned(stmt: Statement<'a>, data: Vec<RowData>) -> Rows<'a> {
5049
Rows {
5150
stmt: MaybeOwned::Owned(stmt),
5251
data: data,
@@ -112,7 +111,7 @@ impl<'a> IntoIterator for &'a Rows<'a> {
112111
/// An iterator over `Row`s.
113112
pub struct Iter<'a> {
114113
stmt: &'a Statement<'a>,
115-
iter: slice::Iter<'a, Vec<Option<Vec<u8>>>>,
114+
iter: slice::Iter<'a, RowData>,
116115
}
117116

118117
impl<'a> Iterator for Iter<'a> {
@@ -148,7 +147,7 @@ impl<'a> ExactSizeIterator for Iter<'a> {}
148147
/// A single result row of a query.
149148
pub struct Row<'a> {
150149
stmt: &'a Statement<'a>,
151-
data: MaybeOwned<'a, Vec<Option<Vec<u8>>>>,
150+
data: MaybeOwned<'a, RowData>,
152151
}
153152

154153
impl<'a> fmt::Debug for Row<'a> {
@@ -238,7 +237,7 @@ impl<'a> Row<'a> {
238237
}
239238
let conn = self.stmt.conn().0.borrow();
240239
let value = FromSql::from_sql_nullable(ty,
241-
self.data[idx].as_ref().map(|r| &**r),
240+
self.data.get(idx),
242241
&SessionInfo::new(&conn.parameters));
243242
Some(value.map_err(Error::Conversion))
244243
}
@@ -252,7 +251,7 @@ impl<'a> Row<'a> {
252251
where I: RowIndex + fmt::Debug
253252
{
254253
match idx.idx(self.stmt) {
255-
Some(idx) => self.data[idx].as_ref().map(|e| &**e),
254+
Some(idx) => self.data.get(idx),
256255
None => panic!("invalid index {:?}", idx),
257256
}
258257
}
@@ -293,7 +292,7 @@ impl<'a> RowIndex for &'a str {
293292
/// A lazily-loaded iterator over the resulting rows of a query.
294293
pub struct LazyRows<'trans, 'stmt> {
295294
stmt: &'stmt Statement<'stmt>,
296-
data: VecDeque<Vec<Option<Vec<u8>>>>,
295+
data: VecDeque<RowData>,
297296
name: String,
298297
row_limit: i32,
299298
more_rows: bool,
@@ -303,7 +302,7 @@ pub struct LazyRows<'trans, 'stmt> {
303302

304303
impl<'trans, 'stmt> LazyRowsNew<'trans, 'stmt> for LazyRows<'trans, 'stmt> {
305304
fn new(stmt: &'stmt Statement<'stmt>,
306-
data: VecDeque<Vec<Option<Vec<u8>>>>,
305+
data: VecDeque<RowData>,
307306
name: String,
308307
row_limit: i32,
309308
more_rows: bool,
@@ -354,7 +353,7 @@ impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
354353
try!(conn.stream.write_message(|buf| frontend::execute(&self.name, self.row_limit, buf)));
355354
try!(conn.stream.write_message(|buf| Ok::<(), io::Error>(frontend::sync(buf))));
356355
try!(conn.stream.flush());
357-
conn.read_rows(&mut self.data).map(|more_rows| self.more_rows = more_rows)
356+
conn.read_rows(|row| self.data.push_back(row)).map(|more_rows| self.more_rows = more_rows)
358357
}
359358

360359
/// Returns a slice describing the columns of the `LazyRows`.

src/stmt.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use error::{Error, DbError};
1212
use types::{SessionInfo, Type, ToSql};
1313
use rows::{Rows, LazyRows};
1414
use transaction::Transaction;
15-
use {bad_response, Connection, StatementInternals, Result, RowsNew, InnerConnection,
15+
use {bad_response, Connection, StatementInternals, Result, RowsNew, InnerConnection, RowData,
1616
SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo, TransactionInternals};
1717

1818
/// A prepared statement.
@@ -59,8 +59,9 @@ impl<'conn> StatementInternals<'conn> for Statement<'conn> {
5959

6060
fn into_query(self, params: &[&ToSql]) -> Result<Rows<'conn>> {
6161
check_desync!(self.conn);
62-
self.inner_query("", 0, params)
63-
.map(|(buf, _)| Rows::new_owned(self, buf.into_iter().collect()))
62+
let mut rows = vec![];
63+
try!(self.inner_query("", 0, params, |row| rows.push(row)));
64+
Ok(Rows::new_owned(self, rows))
6465
}
6566
}
6667

@@ -77,11 +78,14 @@ impl<'conn> Statement<'conn> {
7778
}
7879

7980
#[allow(type_complexity)]
80-
fn inner_query<'a>(&'a self,
81-
portal_name: &str,
82-
row_limit: i32,
83-
params: &[&ToSql])
84-
-> Result<(VecDeque<Vec<Option<Vec<u8>>>>, bool)> {
81+
fn inner_query<F>(&self,
82+
portal_name: &str,
83+
row_limit: i32,
84+
params: &[&ToSql],
85+
acceptor: F)
86+
-> Result<bool>
87+
where F: FnMut(RowData)
88+
{
8589
let mut conn = self.conn.0.borrow_mut();
8690

8791
try!(conn.raw_execute(&self.info.name,
@@ -90,9 +94,7 @@ impl<'conn> Statement<'conn> {
9094
self.param_types(),
9195
params));
9296

93-
let mut buf = VecDeque::new();
94-
let more_rows = try!(conn.read_rows(&mut buf));
95-
Ok((buf, more_rows))
97+
conn.read_rows(acceptor)
9698
}
9799

98100
/// Returns a slice containing the expected parameter types.
@@ -200,7 +202,9 @@ impl<'conn> Statement<'conn> {
200202
/// ```
201203
pub fn query<'a>(&'a self, params: &[&ToSql]) -> Result<Rows<'a>> {
202204
check_desync!(self.conn);
203-
self.inner_query("", 0, params).map(|(buf, _)| Rows::new(self, buf.into_iter().collect()))
205+
let mut rows = vec![];
206+
try!(self.inner_query("", 0, params, |row| rows.push(row)));
207+
Ok(Rows::new(self, rows))
204208
}
205209

206210
/// Executes the prepared statement, returning a lazily loaded iterator
@@ -239,9 +243,12 @@ impl<'conn> Statement<'conn> {
239243
self.next_portal_id.set(id + 1);
240244
let portal_name = format!("{}p{}", self.info.name, id);
241245

242-
self.inner_query(&portal_name, row_limit, params).map(move |(data, more_rows)| {
243-
LazyRows::new(self, data, portal_name, row_limit, more_rows, false, trans)
244-
})
246+
let mut rows = VecDeque::new();
247+
let more_rows = try!(self.inner_query(&portal_name,
248+
row_limit,
249+
params,
250+
|row| rows.push_back(row)));
251+
Ok(LazyRows::new(self, rows, portal_name, row_limit, more_rows, false, trans))
245252
}
246253

247254
/// Executes a `COPY FROM STDIN` statement, returning the number of rows

0 commit comments

Comments
 (0)