Allow arrays with a non-zero lower bound
When I originally implemented support for arrays, I didn't really
understand what `lower_bound` was, and observed it was always 1. For
that reason, I added the assertion that it must be 1 since I didn't know
if our behavior was correct when it was some number other than 1 (at the
time I thought it was related to multidimensional arrays)
So it turns out that it's literally just the index of the first element
of the array. For whatever reason, PG arrays are 1 indexed by default,
and they have a syntax which lets you have arrays starting at *any*
index. Knowing this, we can safely ignore it.
We will continue to give you a zero indexed `Vec` regardless of what the
lower bound is, since the only other alternative would be to always
deserialize to `Vec<Option<T>>`. If we did this, it would mean that
`ARRAY[1, 2, 3]` would deserialize to `vec![None, Some(1), Some(2),
Some(3)]`. While this is technically more faithful to what PG gives us,
I don't think anybody expects that behavior.
diff --git a/diesel/src/pg/types/array.rs b/diesel/src/pg/types/array.rs
index 7ce5a3f..c0f9087 100644
--- a/diesel/src/pg/types/array.rs
+++ b/diesel/src/pg/types/array.rs
@@ -34,14 +34,11 @@
}
let num_elements = try!(bytes.read_i32::<NetworkEndian>());
- let lower_bound = try!(bytes.read_i32::<NetworkEndian>());
+ let _lower_bound = try!(bytes.read_i32::<NetworkEndian>());
if num_dimensions != 1 {
return Err("multi-dimensional arrays are not supported".into());
}
- if lower_bound != 1 {
- return Err("lower bound must be 1".into());
- }
(0..num_elements)
.map(|_| {
diff --git a/diesel_tests/tests/types.rs b/diesel_tests/tests/types.rs
index 7f09e5b..1d8d6ee 100644
--- a/diesel_tests/tests/types.rs
+++ b/diesel_tests/tests/types.rs
@@ -612,6 +612,23 @@
);
}
+#[cfg(feature = "postgres")]
+#[test]
+fn pg_array_from_sql_non_one_lower_bound() {
+ assert_eq!(
+ vec![true, false, true],
+ query_single_value::<Array<Bool>, Vec<bool>>("'[0:2]={t, f, t}'::bool[]")
+ );
+ assert_eq!(
+ vec![true, false, true],
+ query_single_value::<Array<Bool>, Vec<bool>>("'[1:3]={t, f, t}'::bool[]")
+ );
+ assert_eq!(
+ vec![true, false, true],
+ query_single_value::<Array<Bool>, Vec<bool>>("'[2:4]={t, f, t}'::bool[]")
+ );
+}
+
#[test]
#[cfg(feature = "postgres")]
fn to_sql_array() {