Skip to content

Commit 298a047

Browse files
committed
store: Add OidValue::Int4Range and fix block_range binding
Add `OidValue::Int4Range(Bound<i32>, Bound<i32>)` variant to properly deserialize PostgreSQL int4range columns (OID 3904). Update `select_cols` in dsl.rs to bind block_range as `Range<Integer>` instead of using the Bytes placeholder, resolving the existing TODO.
1 parent 1bd0448 commit 298a047

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

store/postgres/src/relational/dsl.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use diesel::query_dsl::methods::SelectDsl;
1616
use diesel::query_source::QuerySource;
1717

1818
use diesel::sql_types::{
19-
Array, BigInt, Binary, Bool, Integer, Nullable, Numeric, SingleValue, Text, Timestamptz,
19+
Array, BigInt, Binary, Bool, Integer, Nullable, Numeric, Range, SingleValue, Text, Timestamptz,
2020
Untyped,
2121
};
2222
use diesel::{AppearsOnTable, Expression, QueryDsl, QueryResult, SelectableExpression};
@@ -43,8 +43,8 @@ lazy_static! {
4343
pub static ref TYPENAME_COL: RelColumn = RelColumn::pseudo_column(TYPENAME, ColumnType::String);
4444
pub static ref VID_COL: RelColumn = RelColumn::pseudo_column("vid", ColumnType::Int8);
4545
pub static ref BLOCK_COL: RelColumn = RelColumn::pseudo_column(BLOCK_COLUMN, ColumnType::Int8);
46-
// The column type is a placeholder, we can't deserialize in4range; but
47-
// we also never try to use it when we get data from the database
46+
// The column type is a placeholder; block_range is deserialized as
47+
// int4range via special handling in select_cols
4848
pub static ref BLOCK_RANGE_COL: RelColumn =
4949
RelColumn::pseudo_column(BLOCK_RANGE_COLUMN, ColumnType::Bytes);
5050
pub static ref PARENT_STRING_COL: RelColumn = RelColumn::pseudo_column(PARENT_ID, ColumnType::String);
@@ -291,7 +291,6 @@ impl<'a> Table<'a> {
291291
if self.meta.immutable {
292292
cols.push(&*BLOCK_COL);
293293
} else {
294-
// TODO: We can't deserialize in4range
295294
cols.push(&*BLOCK_RANGE_COL);
296295
}
297296
}
@@ -348,6 +347,10 @@ impl<'a> Table<'a> {
348347
)));
349348
continue;
350349
}
350+
if column.name == BLOCK_RANGE_COL.name {
351+
selection.add_field(self.bind::<Range<Integer>>(&column.name).unwrap());
352+
continue;
353+
}
351354
match column.column_type {
352355
ColumnType::Boolean => add_field::<Bool>(&mut selection, self, column),
353356
ColumnType::BigDecimal => add_field::<Numeric>(&mut selection, self, column),

store/postgres/src/relational/value.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Helpers to use diesel dynamic schema to retrieve values from Postgres
22
33
use std::num::NonZeroU32;
4+
use std::ops::Bound;
45

5-
use diesel::sql_types::{Array, BigInt, Binary, Bool, Integer, Numeric, Text, Timestamptz};
6+
use diesel::sql_types::{Array, BigInt, Binary, Bool, Integer, Numeric, Range, Text, Timestamptz};
67
use diesel::{deserialize::FromSql, pg::Pg};
78
use diesel_dynamic_schema::dynamic_value::{Any, DynamicRow};
89

@@ -45,6 +46,7 @@ pub enum OidValue {
4546
BigDecimalArray(Vec<BigDecimal>),
4647
Timestamp(Timestamp),
4748
TimestampArray(Vec<Timestamp>),
49+
Int4Range(Bound<i32>, Bound<i32>),
4850
Null,
4951
}
5052

@@ -66,6 +68,7 @@ impl FromSql<Any, Pg> for OidValue {
6668
const NUMERIC_ARY_OID: NonZeroU32 = NonZeroU32::new(1231).unwrap();
6769
const TIMESTAMPTZ_OID: NonZeroU32 = NonZeroU32::new(1184).unwrap();
6870
const TIMESTAMPTZ_ARY_OID: NonZeroU32 = NonZeroU32::new(1185).unwrap();
71+
const INT4RANGE_OID: NonZeroU32 = NonZeroU32::new(3904).unwrap();
6972

7073
match value.get_oid() {
7174
VARCHAR_OID | TEXT_OID => {
@@ -102,6 +105,10 @@ impl FromSql<Any, Pg> for OidValue {
102105
<Vec<Timestamp> as FromSql<Array<Timestamptz>, Pg>>::from_sql(value)
103106
.map(OidValue::TimestampArray)
104107
}
108+
INT4RANGE_OID => {
109+
<(Bound<i32>, Bound<i32>) as FromSql<Range<Integer>, Pg>>::from_sql(value)
110+
.map(|(lo, hi)| OidValue::Int4Range(lo, hi))
111+
}
105112
e => Err(format!("Unknown type: {e}").into()),
106113
}
107114
}
@@ -143,6 +150,11 @@ impl FromOidValue for r::Value {
143150
O::BigDecimalArray(b) => as_list(b, |b| Self::String(b.to_string())),
144151
O::Timestamp(t) => Self::Timestamp(t),
145152
O::TimestampArray(t) => as_list(t, Self::Timestamp),
153+
O::Int4Range(..) => {
154+
return Err(StoreError::InternalError(
155+
"int4range can not be converted to r::Value".to_string(),
156+
))
157+
}
146158
O::Null => Self::Null,
147159
};
148160
Ok(value)
@@ -195,6 +207,11 @@ impl FromOidValue for graph::prelude::Value {
195207
},
196208
O::Timestamp(t) => Self::Timestamp(t),
197209
O::TimestampArray(t) => as_list(t, Self::Timestamp),
210+
O::Int4Range(..) => {
211+
return Err(StoreError::InternalError(
212+
"int4range can not be converted to Value".to_string(),
213+
))
214+
}
198215
O::Null => Self::Null,
199216
};
200217
Ok(value)

0 commit comments

Comments
 (0)