Don't clone cached statement info

This commit is contained in:
Steven Fackler
2016-01-02 21:02:54 -08:00
parent 54735d9f4f
commit a4f0c3bc5f
2 changed files with 46 additions and 48 deletions

View File

@@ -65,6 +65,7 @@ use std::io::prelude::*;
use std::marker::Sync as StdSync;
use std::mem;
use std::result;
use std::sync::Arc;
use std::time::Duration;
#[cfg(feature = "unix_socket")]
use std::path::PathBuf;
@@ -361,8 +362,7 @@ pub enum SslMode<'a> {
Require(&'a NegotiateSsl),
}
#[derive(Clone)]
struct CachedStatement {
struct StatementInfo {
name: String,
param_types: Vec<Type>,
columns: Vec<Column>,
@@ -374,7 +374,7 @@ struct InnerConnection {
notifications: VecDeque<Notification>,
cancel_data: CancelData,
unknown_types: HashMap<Oid, Other>,
cached_statements: HashMap<String, CachedStatement>,
cached_statements: HashMap<String, Arc<StatementInfo>>,
parameters: HashMap<String, String>,
next_stmt_id: u32,
trans_depth: u32,
@@ -670,28 +670,33 @@ impl InnerConnection {
fn prepare<'a>(&mut self, query: &str, conn: &'a Connection) -> Result<Statement<'a>> {
let stmt_name = self.make_stmt_name();
let (param_types, columns) = try!(self.raw_prepare(&stmt_name, query));
Ok(Statement::new(conn, stmt_name, param_types, columns, Cell::new(0), false))
let info = Arc::new(StatementInfo {
name: stmt_name,
param_types: param_types,
columns: columns,
});
Ok(Statement::new(conn, info, Cell::new(0), false))
}
fn prepare_cached<'a>(&mut self, query: &str, conn: &'a Connection) -> Result<Statement<'a>> {
let stmt = self.cached_statements.get(query).cloned();
let info = self.cached_statements.get(query).cloned();
let CachedStatement { name, param_types, columns } = match stmt {
Some(stmt) => stmt,
let info = match info {
Some(info) => info,
None => {
let stmt_name = self.make_stmt_name();
let (param_types, columns) = try!(self.raw_prepare(&stmt_name, query));
let stmt = CachedStatement {
let info = Arc::new(StatementInfo {
name: stmt_name,
param_types: param_types,
columns: columns,
};
self.cached_statements.insert(query.to_owned(), stmt.clone());
stmt
});
self.cached_statements.insert(query.to_owned(), info.clone());
info
}
};
Ok(Statement::new(conn, name, param_types, columns, Cell::new(0), true))
Ok(Statement::new(conn, info, Cell::new(0), true))
}
fn close_statement(&mut self, name: &str, type_: u8) -> Result<()> {
@@ -959,12 +964,12 @@ impl Connection {
/// ```
pub fn execute(&self, query: &str, params: &[&ToSql]) -> Result<u64> {
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);
let info = Arc::new(StatementInfo {
name: String::new(),
param_types: param_types,
columns: columns,
});
let stmt = Statement::new(self, info, Cell::new(0), true);
stmt.execute(params)
}
@@ -995,12 +1000,12 @@ impl Connection {
/// ```
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);
let info = Arc::new(StatementInfo {
name: String::new(),
param_types: param_types,
columns: columns,
});
let stmt = Statement::new(self, info, Cell::new(0), true);
stmt.into_query(params)
}
@@ -1497,9 +1502,7 @@ trait SessionInfoNew<'a> {
trait StatementInternals<'conn> {
fn new(conn: &'conn Connection,
name: String,
param_types: Vec<Type>,
columns: Vec<Column>,
info: Arc<StatementInfo>,
next_portal_id: Cell<u32>,
finished: bool)
-> Statement<'conn>;

View File

@@ -4,6 +4,7 @@ use std::cell::{Cell, RefMut};
use std::collections::VecDeque;
use std::fmt;
use std::io::{self, Read, Write};
use std::sync::Arc;
use error::{Error, DbError};
use types::{SessionInfo, Type, ToSql, IsNull};
@@ -13,14 +14,12 @@ use message::WriteMessage;
use util;
use rows::{Rows, LazyRows};
use {read_rows, bad_response, Connection, Transaction, StatementInternals, Result, RowsNew};
use {InnerConnection, SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew};
use {InnerConnection, SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo};
/// A prepared statement.
pub struct Statement<'conn> {
conn: &'conn Connection,
name: String,
param_types: Vec<Type>,
columns: Vec<Column>,
info: Arc<StatementInfo>,
next_portal_id: Cell<u32>,
finished: bool,
}
@@ -28,9 +27,9 @@ pub struct Statement<'conn> {
impl<'a> fmt::Debug for Statement<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Statement")
.field("name", &self.name)
.field("parameter_types", &self.param_types)
.field("columns", &self.columns)
.field("name", &self.info.name)
.field("parameter_types", &self.info.param_types)
.field("columns", &self.info.columns)
.finish()
}
}
@@ -43,17 +42,13 @@ impl<'conn> Drop for Statement<'conn> {
impl<'conn> StatementInternals<'conn> for Statement<'conn> {
fn new(conn: &'conn Connection,
name: String,
param_types: Vec<Type>,
columns: Vec<Column>,
info: Arc<StatementInfo>,
next_portal_id: Cell<u32>,
finished: bool)
-> Statement<'conn> {
Statement {
conn: conn,
name: name,
param_types: param_types,
columns: columns,
info: info,
next_portal_id: next_portal_id,
finished: finished,
}
@@ -76,7 +71,7 @@ impl<'conn> Statement<'conn> {
self.finished = true;
let mut conn = self.conn.conn.borrow_mut();
check_desync!(conn);
conn.close_statement(&self.name, b'S')
conn.close_statement(&self.info.name, b'S')
} else {
Ok(())
}
@@ -86,13 +81,13 @@ impl<'conn> Statement<'conn> {
let mut conn = self.conn.conn.borrow_mut();
assert!(self.param_types().len() == params.len(),
"expected {} parameters but got {}",
self.param_types.len(),
self.param_types().len(),
params.len());
debug!("executing statement {} with parameters: {:?}",
self.name,
self.info.name,
params);
let mut values = vec![];
for (param, ty) in params.iter().zip(self.param_types.iter()) {
for (param, ty) in params.iter().zip(self.param_types()) {
let mut buf = vec![];
match try!(param.to_sql_checked(ty, &mut buf, &SessionInfo::new(&*conn))) {
IsNull::Yes => values.push(None),
@@ -102,7 +97,7 @@ impl<'conn> Statement<'conn> {
try!(conn.write_messages(&[Bind {
portal: portal_name,
statement: &self.name,
statement: &self.info.name,
formats: &[1],
values: &values,
result_formats: &[1],
@@ -140,12 +135,12 @@ impl<'conn> Statement<'conn> {
/// Returns a slice containing the expected parameter types.
pub fn param_types(&self) -> &[Type] {
&self.param_types
&self.info.param_types
}
/// Returns a slice describing the columns of the result of the query.
pub fn columns(&self) -> &[Column] {
&self.columns
&self.info.columns
}
/// Executes the prepared statement, returning the number of rows modified.
@@ -279,7 +274,7 @@ impl<'conn> Statement<'conn> {
let id = self.next_portal_id.get();
self.next_portal_id.set(id + 1);
let portal_name = format!("{}p{}", self.name, id);
let portal_name = format!("{}p{}", self.info.name, id);
self.inner_query(&portal_name, row_limit, params).map(move |(data, more_rows)| {
LazyRows::new(self, data, portal_name, row_limit, more_rows, false, trans)