Don't clone cached statement info
This commit is contained in:
57
src/lib.rs
57
src/lib.rs
@@ -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>;
|
||||
|
||||
37
src/stmt.rs
37
src/stmt.rs
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user