Add Connection::query

Same deal as Connection::execute - a bit cheaper than preparing and
executing the statement normally.
This commit is contained in:
Steven Fackler 2015-11-13 19:34:11 -08:00
parent fcc2768434
commit 736f530ae9
4 changed files with 49 additions and 0 deletions

View File

@ -930,6 +930,23 @@ impl Connection {
stmt.execute(params)
}
/// A convenience function for queries that are only run once.
///
/// If an error is returned, it could have come from either the preparation
/// or execution of the statement.
///
/// On success, returns the resulting rows.
///
/// ## Panics
///
/// Panics if the number of parameters provided does not match the number
/// expected.
pub fn query<'a>(&'a self, query: &str, params: &[&ToSql]) -> Result<Rows<'a>> {
let (param_types, columns) = try!(self.conn.borrow_mut().raw_prepare("", query));
let stmt = Statement::new(self, "".to_owned(), param_types, columns, Cell::new(0), true);
stmt.into_query(params)
}
/// Begins a new transaction.
///
/// Returns a `Transaction` object which should be used instead of
@ -1386,6 +1403,7 @@ trait DbErrorNew {
trait RowsNew<'a> {
fn new(stmt: &'a Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a>;
fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a>;
}
trait LazyRowsNew<'trans, 'stmt> {
@ -1413,6 +1431,8 @@ trait StatementInternals<'conn> {
-> Statement<'conn>;
fn conn(&self) -> &'conn Connection;
fn into_query(self, params: &[&ToSql]) -> Result<Rows<'conn>>;
}
trait ColumnNew {

View File

@ -43,6 +43,13 @@ impl<'a> RowsNew<'a> for Rows<'a> {
data: data,
}
}
fn new_owned(stmt: Statement<'a>, data: Vec<Vec<Option<Vec<u8>>>>) -> Rows<'a> {
Rows {
stmt: StatementContainer::Owned(stmt),
data: data,
}
}
}
impl<'a> fmt::Debug for Rows<'a> {

View File

@ -62,6 +62,13 @@ impl<'conn> StatementInternals<'conn> for Statement<'conn> {
fn conn(&self) -> &'conn Connection {
self.conn
}
fn into_query(self, params: &[&ToSql]) -> Result<Rows<'conn>> {
check_desync!(self.conn);
self.inner_query("", 0, params).map(|(buf, _)| {
Rows::new_owned(self, buf.into_iter().collect())
})
}
}
impl<'conn> Statement<'conn> {

View File

@ -1001,3 +1001,18 @@ fn test_type_names() {
assert_eq!(Type::from_oid(id).unwrap().name(), name);
}
}
#[test]
fn test_conn_query() {
let conn = Connection::connect("postgres://postgres@localhost", &SslMode::None).unwrap();
conn.batch_execute("
CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY);
INSERT INTO foo (id) VALUES (1), (2), (3);
").unwrap();
let ids = conn.query("SELECT id FROM foo ORDER BY id", &[])
.unwrap()
.iter()
.map(|r| r.get(0))
.collect::<Vec<i32>>();
assert_eq!(ids, [1, 2, 3]);
}