Skip to content

Commit d602574

Browse files
committed
Add a possiblity to get a PgMetadataLookup inside FromSql implementations
1 parent ba752f8 commit d602574

11 files changed

Lines changed: 75 additions & 52 deletions

File tree

diesel/src/pg/connection/cursor.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use std::marker::PhantomData;
99

1010
/// The type returned by various [`Connection`](struct.Connection.html) methods.
1111
/// Acts as an iterator over `T`.
12-
pub struct Cursor<ST, T> {
12+
pub struct Cursor<'a, ST, T> {
1313
current_row: usize,
14-
db_result: PgResult,
14+
db_result: PgResult<'a>,
1515
_marker: PhantomData<(ST, T)>,
1616
}
1717

18-
impl<ST, T> Cursor<ST, T> {
18+
impl<'a, ST, T> Cursor<'a, ST, T> {
1919
#[doc(hidden)]
20-
pub fn new(db_result: PgResult) -> Self {
20+
pub fn new(db_result: PgResult<'a>) -> Self {
2121
Cursor {
2222
current_row: 0,
2323
db_result,
@@ -26,7 +26,7 @@ impl<ST, T> Cursor<ST, T> {
2626
}
2727
}
2828

29-
impl<ST, T> Iterator for Cursor<ST, T>
29+
impl<'a, ST, T> Iterator for Cursor<'a, ST, T>
3030
where
3131
T: Queryable<ST, Pg>,
3232
{
@@ -46,12 +46,12 @@ where
4646
}
4747
}
4848

49-
pub struct NamedCursor {
50-
pub(crate) db_result: PgResult,
49+
pub struct NamedCursor<'a> {
50+
pub(crate) db_result: PgResult<'a>,
5151
}
5252

53-
impl NamedCursor {
54-
pub fn new(db_result: PgResult) -> Self {
53+
impl<'a> NamedCursor<'a> {
54+
pub fn new(db_result: PgResult<'a>) -> Self {
5555
NamedCursor { db_result }
5656
}
5757

diesel/src/pg/connection/mod.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use sql_types::HasSqlType;
2626
/// <https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNSTRING>
2727
#[allow(missing_debug_implementations)]
2828
pub struct PgConnection {
29-
raw_connection: RawConnection,
29+
pub(crate) raw_connection: RawConnection,
3030
transaction_manager: AnsiTransactionManager,
3131
statement_cache: StatementCache<Pg, Statement>,
3232
metadata_cache: PgMetadataCache,
@@ -38,7 +38,7 @@ impl SimpleConnection for PgConnection {
3838
fn batch_execute(&self, query: &str) -> QueryResult<()> {
3939
let query = CString::new(query)?;
4040
let inner_result = unsafe { self.raw_connection.exec(query.as_ptr()) };
41-
PgResult::new(inner_result?)?;
41+
PgResult::new(inner_result?, self)?;
4242
Ok(())
4343
}
4444
}
@@ -76,7 +76,7 @@ impl Connection for PgConnection {
7676
{
7777
let (query, params) = self.prepare_query(&source.as_query())?;
7878
query
79-
.execute(&self.raw_connection, &params)
79+
.execute(self, &params)
8080
.and_then(|r| Cursor::new(r).collect())
8181
}
8282

@@ -88,7 +88,7 @@ impl Connection for PgConnection {
8888
{
8989
let (query, params) = self.prepare_query(source)?;
9090
query
91-
.execute(&self.raw_connection, &params)
91+
.execute(self, &params)
9292
.and_then(|r| NamedCursor::new(r).collect())
9393
}
9494

@@ -98,9 +98,7 @@ impl Connection for PgConnection {
9898
T: QueryFragment<Pg> + QueryId,
9999
{
100100
let (query, params) = self.prepare_query(source)?;
101-
query
102-
.execute(&self.raw_connection, &params)
103-
.map(|r| r.rows_affected())
101+
query.execute(self, &params).map(|r| r.rows_affected())
104102
}
105103

106104
#[doc(hidden)]
@@ -157,20 +155,15 @@ impl PgConnection {
157155
} else {
158156
None
159157
};
160-
Statement::prepare(
161-
&self.raw_connection,
162-
sql,
163-
query_name.as_ref().map(|s| &**s),
164-
&metadata,
165-
)
158+
Statement::prepare(self, sql, query_name.as_ref().map(|s| &**s), &metadata)
166159
});
167160

168161
Ok((query?, binds))
169162
}
170163

171164
fn execute_inner(&self, query: &str) -> QueryResult<PgResult> {
172-
let query = Statement::prepare(&self.raw_connection, query, None, &[])?;
173-
query.execute(&self.raw_connection, &Vec::new())
165+
let query = Statement::prepare(self, query, None, &[])?;
166+
query.execute(self, &Vec::new())
174167
}
175168

176169
fn set_config_options(&self) -> QueryResult<()> {

diesel/src/pg/connection/result.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,25 @@ use std::{slice, str};
88

99
use super::raw::RawResult;
1010
use super::row::PgRow;
11+
use pg::PgConnection;
1112
use result::{DatabaseErrorInformation, DatabaseErrorKind, Error, QueryResult};
1213

13-
pub struct PgResult {
14+
pub struct PgResult<'a> {
1415
internal_result: RawResult,
16+
pub(crate) connection: &'a PgConnection,
1517
}
1618

17-
impl PgResult {
19+
impl<'a> PgResult<'a> {
1820
#[allow(clippy::new_ret_no_self)]
19-
pub fn new(internal_result: RawResult) -> QueryResult<Self> {
21+
pub fn new(internal_result: RawResult, connection: &'a PgConnection) -> QueryResult<Self> {
2022
use self::ExecStatusType::*;
2123

2224
let result_status = unsafe { PQresultStatus(internal_result.as_ptr()) };
2325
match result_status {
24-
PGRES_COMMAND_OK | PGRES_TUPLES_OK => Ok(PgResult { internal_result }),
26+
PGRES_COMMAND_OK | PGRES_TUPLES_OK => Ok(PgResult {
27+
internal_result,
28+
connection,
29+
}),
2530
PGRES_EMPTY_QUERY => {
2631
let error_message = "Received an empty query".to_string();
2732
Err(Error::DatabaseError(

diesel/src/pg/connection/row.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::cursor::NamedCursor;
22
use super::result::PgResult;
3-
use pg::{Pg, PgValue};
3+
use pg::{Pg, PgMetadataLookup, PgValue};
44
use row::*;
55

66
pub struct PgRow<'a> {
7-
db_result: &'a PgResult,
7+
db_result: &'a PgResult<'a>,
88
row_idx: usize,
99
col_idx: usize,
1010
}
@@ -25,7 +25,11 @@ impl<'a> Row<Pg> for PgRow<'a> {
2525
self.col_idx += 1;
2626
let raw = self.db_result.get(self.row_idx, current_idx)?;
2727

28-
Some(PgValue::new(raw, self.db_result.column_type(current_idx)))
28+
Some(PgValue::new(
29+
raw,
30+
self.db_result.column_type(current_idx),
31+
PgMetadataLookup::new(self.db_result.connection),
32+
))
2933
}
3034

3135
fn next_is_null(&self, count: usize) -> bool {
@@ -34,7 +38,7 @@ impl<'a> Row<Pg> for PgRow<'a> {
3438
}
3539

3640
pub struct PgNamedRow<'a> {
37-
cursor: &'a NamedCursor,
41+
cursor: &'a NamedCursor<'a>,
3842
idx: usize,
3943
}
4044

@@ -47,7 +51,11 @@ impl<'a> PgNamedRow<'a> {
4751
impl<'a> NamedRow<Pg> for PgNamedRow<'a> {
4852
fn get_raw_value(&self, index: usize) -> Option<PgValue> {
4953
let raw = self.cursor.get_value(self.idx, index)?;
50-
Some(PgValue::new(raw, self.cursor.db_result.column_type(index)))
54+
Some(PgValue::new(
55+
raw,
56+
self.cursor.db_result.column_type(index),
57+
PgMetadataLookup::new(self.cursor.db_result.connection),
58+
))
5159
}
5260

5361
fn index_of(&self, column_name: &str) -> Option<usize> {

diesel/src/pg/connection/stmt/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::os::raw as libc;
55
use std::ptr;
66

77
use super::result::PgResult;
8-
use pg::PgTypeMetadata;
8+
use pg::{PgConnection, PgTypeMetadata};
99
use result::QueryResult;
1010

1111
pub use super::raw::RawConnection;
@@ -17,11 +17,11 @@ pub struct Statement {
1717

1818
impl Statement {
1919
#[allow(clippy::ptr_arg)]
20-
pub fn execute(
20+
pub fn execute<'a>(
2121
&self,
22-
conn: &RawConnection,
22+
conn: &'a PgConnection,
2323
param_data: &Vec<Option<Vec<u8>>>,
24-
) -> QueryResult<PgResult> {
24+
) -> QueryResult<PgResult<'a>> {
2525
let params_pointer = param_data
2626
.iter()
2727
.map(|data| {
@@ -35,7 +35,7 @@ impl Statement {
3535
.map(|data| data.as_ref().map(|d| d.len() as libc::c_int).unwrap_or(0))
3636
.collect::<Vec<_>>();
3737
let internal_res = unsafe {
38-
conn.exec_prepared(
38+
conn.raw_connection.exec_prepared(
3939
self.name.as_ptr(),
4040
params_pointer.len() as libc::c_int,
4141
params_pointer.as_ptr(),
@@ -45,12 +45,12 @@ impl Statement {
4545
)
4646
};
4747

48-
PgResult::new(internal_res?)
48+
PgResult::new(internal_res?, conn)
4949
}
5050

5151
#[allow(clippy::ptr_arg)]
5252
pub fn prepare(
53-
conn: &RawConnection,
53+
conn: &PgConnection,
5454
sql: &str,
5555
name: Option<&str>,
5656
param_types: &[PgTypeMetadata],
@@ -60,17 +60,17 @@ impl Statement {
6060
let param_types_vec = param_types.iter().map(|x| x.oid).collect();
6161

6262
let internal_result = unsafe {
63-
conn.prepare(
63+
conn.raw_connection.prepare(
6464
name.as_ptr(),
6565
sql.as_ptr(),
6666
param_types.len() as libc::c_int,
6767
param_types_to_ptr(Some(&param_types_vec)),
6868
)
6969
};
70-
PgResult::new(internal_result?)?;
70+
PgResult::new(internal_result?, conn)?;
7171

7272
Ok(Statement {
73-
name: name,
73+
name,
7474
param_formats: vec![1; param_types.len()],
7575
})
7676
}

diesel/src/pg/types/array.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ where
4949
} else {
5050
let (elem_bytes, new_bytes) = bytes.split_at(elem_size as usize);
5151
bytes = new_bytes;
52-
T::from_sql(Some(PgValue::new(elem_bytes, value.get_oid())))
52+
T::from_sql(Some(PgValue::new(
53+
elem_bytes,
54+
value.get_oid(),
55+
value.get_metadata_lookup(),
56+
)))
5357
}
5458
})
5559
.collect()

diesel/src/pg/types/date_and_time/deprecated_time.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ impl ToSql<sql_types::Timestamp, Pg> for Timespec {
2828

2929
impl FromSql<sql_types::Timestamp, Pg> for Timespec {
3030
fn from_sql(bytes: Option<PgValue>) -> deserialize::Result<Self> {
31-
let t = <i64 as FromSql<sql_types::BigInt, Pg>>::from_sql(
32-
bytes,
33-
)?;
31+
let t = <i64 as FromSql<sql_types::BigInt, Pg>>::from_sql(bytes)?;
3432
let pg_epoch = Timespec::new(TIME_SEC_CONV, 0);
3533
let duration = Duration::microseconds(t);
3634
let out = pg_epoch + duration;

diesel/src/pg/types/date_and_time/std_time.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ impl ToSql<sql_types::Timestamp, Pg> for SystemTime {
2828

2929
impl FromSql<sql_types::Timestamp, Pg> for SystemTime {
3030
fn from_sql(bytes: Option<PgValue>) -> deserialize::Result<Self> {
31-
let usecs_passed = <i64 as FromSql<sql_types::BigInt, Pg>>::from_sql(
32-
bytes,
33-
)?;
31+
let usecs_passed = <i64 as FromSql<sql_types::BigInt, Pg>>::from_sql(bytes)?;
3432
let before_epoch = usecs_passed < 0;
3533
let time_passed = usecs_to_duration(usecs_passed.abs() as u64);
3634

diesel/src/pg/types/ranges.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ where
9292
let value = T::from_sql(Some(PgValue::new(
9393
elem_bytes,
9494
value.get_oid(),
95+
value.get_metadata_lookup(),
9596
)))?;
9697

9798
lower_bound = if flags.contains(RangeFlags::LB_INC) {
@@ -106,6 +107,7 @@ where
106107
let value = T::from_sql(Some(PgValue::new(
107108
bytes,
108109
value.get_oid(),
110+
value.get_metadata_lookup(),
109111
)))?;
110112

111113
upper_bound = if flags.contains(RangeFlags::UB_INC) {

diesel/src/pg/types/record.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ macro_rules! tuple_impls {
5151
} else {
5252
let (elem_bytes, new_bytes) = bytes.split_at(num_bytes as usize);
5353
bytes = new_bytes;
54-
$T::from_sql(Some(PgValue::new(elem_bytes, oid)))?
54+
$T::from_sql(Some(PgValue::new(
55+
elem_bytes,
56+
oid,
57+
value.get_metadata_lookup()
58+
)))?
5559
}
5660
},)+);
5761

0 commit comments

Comments
 (0)