Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a33bcb8

Browse files
authored
Merge pull request sfackler#344 from sfackler/auto-flags
Automatically determine flags for array serialization
2 parents 77b3f77 + bfdb557 commit a33bcb8

File tree

2 files changed

+59
-21
lines changed

2 files changed

+59
-21
lines changed

postgres-protocol/src/types.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Conversions to and from Postgres's binary format for various types.
2-
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
2+
use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
33
use fallible_iterator::FallibleIterator;
4+
use std::boxed::Box as StdBox;
45
use std::error::Error;
56
use std::str;
6-
use std::boxed::Box as StdBox;
77

8-
use {Oid, IsNull, write_nullable, FromUsize};
8+
use {write_nullable, FromUsize, IsNull, Oid};
99

1010
const RANGE_UPPER_UNBOUNDED: u8 = 0b0001_0000;
1111
const RANGE_LOWER_UNBOUNDED: u8 = 0b0000_1000;
@@ -189,9 +189,7 @@ where
189189
}
190190

191191
let count = i32::from_usize(count)?;
192-
(&mut buf[base..base + 4])
193-
.write_i32::<BigEndian>(count)
194-
.unwrap();
192+
BigEndian::write_i32(&mut buf[base..], count);
195193

196194
Ok(())
197195
}
@@ -424,7 +422,6 @@ pub fn uuid_from_sql(buf: &[u8]) -> Result<[u8; 16], StdBox<Error + Sync + Send>
424422
#[inline]
425423
pub fn array_to_sql<T, I, J, F>(
426424
dimensions: I,
427-
has_nulls: bool,
428425
element_type: Oid,
429426
elements: J,
430427
mut serializer: F,
@@ -437,7 +434,8 @@ where
437434
{
438435
let dimensions_idx = buf.len();
439436
buf.extend_from_slice(&[0; 4]);
440-
buf.write_i32::<BigEndian>(has_nulls as i32).unwrap();
437+
let flags_idx = buf.len();
438+
buf.extend_from_slice(&[0; 4]);
441439
buf.write_u32::<BigEndian>(element_type).unwrap();
442440

443441
let mut num_dimensions = 0;
@@ -448,14 +446,24 @@ where
448446
}
449447

450448
let num_dimensions = i32::from_usize(num_dimensions)?;
451-
(&mut buf[dimensions_idx..dimensions_idx + 4])
452-
.write_i32::<BigEndian>(num_dimensions)
453-
.unwrap();
449+
BigEndian::write_i32(&mut buf[dimensions_idx..], num_dimensions);
454450

451+
let mut has_nulls = false;
455452
for element in elements {
456-
write_nullable(|buf| serializer(element, buf), buf)?;
453+
write_nullable(
454+
|buf| {
455+
let r = serializer(element, buf);
456+
if let Ok(IsNull::Yes) = r {
457+
has_nulls = true;
458+
}
459+
r
460+
},
461+
buf,
462+
)?;
457463
}
458464

465+
BigEndian::write_i32(&mut buf[flags_idx..], has_nulls as i32);
466+
459467
Ok(())
460468
}
461469

@@ -674,9 +682,7 @@ where
674682
IsNull::No => i32::from_usize(buf.len() - base - 4)?,
675683
IsNull::Yes => -1,
676684
};
677-
(&mut buf[base..base + 4])
678-
.write_i32::<BigEndian>(len)
679-
.unwrap();
685+
BigEndian::write_i32(&mut buf[base..], len);
680686
}
681687
None => buf.truncate(base),
682688
}
@@ -862,9 +868,7 @@ where
862868
}
863869

864870
let num_points = i32::from_usize(num_points)?;
865-
(&mut buf[points_idx..])
866-
.write_i32::<BigEndian>(num_points)
867-
.unwrap();
871+
BigEndian::write_i32(&mut buf[points_idx..], num_points);
868872

869873
Ok(())
870874
}
@@ -941,8 +945,8 @@ impl<'a> FallibleIterator for PathPoints<'a> {
941945

942946
#[cfg(test)]
943947
mod test {
944-
use std::collections::HashMap;
945948
use fallible_iterator::FallibleIterator;
949+
use std::collections::HashMap;
946950

947951
use super::*;
948952
use IsNull;
@@ -1039,7 +1043,6 @@ mod test {
10391043
let mut buf = vec![];
10401044
array_to_sql(
10411045
dimensions.iter().cloned(),
1042-
true,
10431046
10,
10441047
values.iter().cloned(),
10451048
|v, buf| match v {
@@ -1058,4 +1061,40 @@ mod test {
10581061
assert_eq!(array.dimensions().collect::<Vec<_>>().unwrap(), dimensions);
10591062
assert_eq!(array.values().collect::<Vec<_>>().unwrap(), values);
10601063
}
1064+
1065+
#[test]
1066+
fn non_null_array() {
1067+
let dimensions = [
1068+
ArrayDimension {
1069+
len: 1,
1070+
lower_bound: 10,
1071+
},
1072+
ArrayDimension {
1073+
len: 2,
1074+
lower_bound: 0,
1075+
},
1076+
];
1077+
let values = [Some(&b"hola"[..]), Some(&b"hello"[..])];
1078+
1079+
let mut buf = vec![];
1080+
array_to_sql(
1081+
dimensions.iter().cloned(),
1082+
10,
1083+
values.iter().cloned(),
1084+
|v, buf| match v {
1085+
Some(v) => {
1086+
buf.extend_from_slice(v);
1087+
Ok(IsNull::No)
1088+
}
1089+
None => Ok(IsNull::Yes),
1090+
},
1091+
&mut buf,
1092+
).unwrap();
1093+
1094+
let array = array_from_sql(&buf).unwrap();
1095+
assert_eq!(array.has_nulls(), false);
1096+
assert_eq!(array.element_type(), 10);
1097+
assert_eq!(array.dimensions().collect::<Vec<_>>().unwrap(), dimensions);
1098+
assert_eq!(array.values().collect::<Vec<_>>().unwrap(), values);
1099+
}
10611100
}

postgres-shared/src/types/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,6 @@ impl<'a, T: ToSql> ToSql for &'a [T] {
588588

589589
types::array_to_sql(
590590
Some(dimension),
591-
true,
592591
member_type.oid(),
593592
self.iter(),
594593
|e, w| match e.to_sql(member_type, w)? {

0 commit comments

Comments
 (0)