Skip to content

Commit a748348

Browse files
committed
Support INT4RANGE[]
1 parent 5471b7d commit a748348

3 files changed

Lines changed: 126 additions & 127 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ types. The driver currently supports the following conversions:
302302
<td>types::array::ArrayBase&lt;Option&lt;extra::uuid::Uuid&gt;&gt;</td>
303303
<td>UUID[], UUID[][], ...</td>
304304
</tr>
305+
<tr>
306+
<td>types::array::ArrayBase&lt;Option&lt;types::range::Range&lt;i32&gt;&gt;&gt;</td>
307+
<td>INT4RANGE[], INT4RANGE[][], ...</td>
308+
</tr>
305309
<tr>
306310
<td>std::hashmap::HashMap&lt;~str, Option&lt;~str&gt;&gt;</td>
307311
<td>HSTORE</td>

test.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,14 @@ fn test_uuidarray_params() {
513513
test_array_params!("UUID", v1, s1, v2, s2, v3, s3);
514514
}
515515
516+
#[test]
517+
fn test_int4rangearray_params() {
518+
test_array_params!("INT4RANGE",
519+
Range::new(None, None), "\"(,)\"",
520+
Range::new(Some(RangeBound::new(10i32, Inclusive)), None), "\"[10,)\"",
521+
Range::new(None, Some(RangeBound::new(10i32, Exclusive))), "\"(,10)\"");
522+
}
523+
516524
#[test]
517525
fn test_hstore_params() {
518526
macro_rules! make_map(

types/mod.rs

Lines changed: 114 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use extra::uuid::Uuid;
99
use std::hashmap::HashMap;
1010
use std::io::Decorator;
1111
use std::io::mem::{MemWriter, BufReader};
12-
use std::mem;
1312
use std::str;
1413
use std::vec;
1514

@@ -53,6 +52,7 @@ static TIMESTAMPZARRAYOID: Oid = 1185;
5352
static UUIDOID: Oid = 2950;
5453
static UUIDARRAYOID: Oid = 2951;
5554
static INT4RANGEOID: Oid = 3904;
55+
static INT4RANGEARRAYOID: Oid = 3905;
5656
static TSRANGEOID: Oid = 3908;
5757
static TSTZRANGEOID: Oid = 3910;
5858
static INT8RANGEOID: Oid = 3926;
@@ -188,6 +188,8 @@ make_postgres_type!(
188188
UUIDARRAYOID => PgUuidArray member PgUuid,
189189
#[doc="INT4RANGE"]
190190
INT4RANGEOID => PgInt4Range,
191+
#[doc="INT4RANGE[]"]
192+
INT4RANGEARRAYOID => PgInt4RangeArray member PgInt4Range,
191193
#[doc="INT8RANGE"]
192194
INT8RANGEOID => PgInt8Range,
193195
#[doc="TSRANGE"]
@@ -285,6 +287,51 @@ impl RawFromSql for Uuid {
285287
}
286288
}
287289

290+
macro_rules! from_range_impl(
291+
($($oid:ident)|+, $t:ty) => (
292+
impl RawFromSql for Range<$t> {
293+
fn raw_from_sql<R: Reader>(_len: uint, rdr: &mut R) -> Range<$t> {
294+
let t = rdr.read_i8();
295+
296+
if t & RANGE_EMPTY != 0 {
297+
Range::empty()
298+
} else {
299+
let lower = match t & RANGE_LOWER_UNBOUNDED {
300+
0 => {
301+
let type_ = match t & RANGE_LOWER_INCLUSIVE {
302+
0 => Exclusive,
303+
_ => Inclusive
304+
};
305+
let len = rdr.read_be_i32() as uint;
306+
Some(RangeBound::new(
307+
RawFromSql::raw_from_sql(len, rdr), type_))
308+
}
309+
_ => None
310+
};
311+
let upper = match t & RANGE_UPPER_UNBOUNDED {
312+
0 => {
313+
let type_ = match t & RANGE_UPPER_INCLUSIVE {
314+
0 => Exclusive,
315+
_ => Inclusive
316+
};
317+
let len = rdr.read_be_i32() as uint;
318+
Some(RangeBound::new(
319+
RawFromSql::raw_from_sql(len, rdr), type_))
320+
}
321+
_ => None
322+
};
323+
324+
Range::new(lower, upper)
325+
}
326+
}
327+
}
328+
)
329+
)
330+
331+
from_range_impl!(PgInt4Range, i32)
332+
from_range_impl!(PgInt8Range, i64)
333+
from_range_impl!(PgTsRange | PgTstzRange, Timespec)
334+
288335
macro_rules! from_map_impl(
289336
($($expected:pat)|+, $t:ty, $blk:expr) => (
290337
impl FromSql for Option<$t> {
@@ -329,50 +376,9 @@ from_map_impl!(PgJson, Json, |buf| {
329376
})
330377

331378
from_raw_from_impl!(PgTimestamp | PgTimestampTZ, Timespec)
332-
333-
macro_rules! from_range_impl(
334-
($($oid:ident)|+, $t:ty) => (
335-
from_map_impl!($($oid)|+, Range<$t>, |buf| {
336-
let mut rdr = BufReader::new(buf.as_slice());
337-
let t = rdr.read_i8();
338-
339-
if t & RANGE_EMPTY != 0 {
340-
Range::empty()
341-
} else {
342-
let lower = match t & RANGE_LOWER_UNBOUNDED {
343-
0 => {
344-
let type_ = match t & RANGE_LOWER_INCLUSIVE {
345-
0 => Exclusive,
346-
_ => Inclusive
347-
};
348-
let len = rdr.read_be_i32() as uint;
349-
Some(RangeBound::new(
350-
RawFromSql::raw_from_sql(len, &mut rdr), type_))
351-
}
352-
_ => None
353-
};
354-
let upper = match t & RANGE_UPPER_UNBOUNDED {
355-
0 => {
356-
let type_ = match t & RANGE_UPPER_INCLUSIVE {
357-
0 => Exclusive,
358-
_ => Inclusive
359-
};
360-
let len = rdr.read_be_i32() as uint;
361-
Some(RangeBound::new(
362-
RawFromSql::raw_from_sql(len, &mut rdr), type_))
363-
}
364-
_ => None
365-
};
366-
367-
Range::new(lower, upper)
368-
}
369-
})
370-
)
371-
)
372-
373-
from_range_impl!(PgInt4Range, i32)
374-
from_range_impl!(PgInt8Range, i64)
375-
from_range_impl!(PgTsRange | PgTstzRange, Timespec)
379+
from_raw_from_impl!(PgInt4Range, Range<i32>)
380+
from_raw_from_impl!(PgInt8Range, Range<i64>)
381+
from_raw_from_impl!(PgTsRange | PgTstzRange, Range<Timespec>)
376382

377383
macro_rules! from_array_impl(
378384
($($oid:ident)|+, $t:ty) => (
@@ -419,6 +425,7 @@ from_array_impl!(PgTimestampArray | PgTimestampTZArray, Timespec)
419425
from_array_impl!(PgFloat4Array, f32)
420426
from_array_impl!(PgFloat8Array, f64)
421427
from_array_impl!(PgUuidArray, Uuid)
428+
from_array_impl!(PgInt4RangeArray, Range<i32>)
422429

423430
from_map_impl!(PgUnknownType { name: ~"hstore", .. },
424431
HashMap<~str, Option<~str>>, |buf| {
@@ -458,8 +465,6 @@ pub trait ToSql {
458465
459466
trait RawToSql {
460467
fn raw_to_sql<W: Writer>(&self, w: &mut W);
461-
462-
fn raw_size(&self) -> uint;
463468
}
464469
465470
macro_rules! raw_to_impl(
@@ -468,10 +473,6 @@ macro_rules! raw_to_impl(
468473
fn raw_to_sql<W: Writer>(&self, w: &mut W) {
469474
w.$f(*self)
470475
}
471-
472-
fn raw_size(&self) -> uint {
473-
mem::size_of::<$t>()
474-
}
475476
}
476477
)
477478
)
@@ -480,30 +481,18 @@ impl RawToSql for bool {
480481
fn raw_to_sql<W: Writer>(&self, w: &mut W) {
481482
w.write_u8(*self as u8)
482483
}
483-
484-
fn raw_size(&self) -> uint {
485-
1
486-
}
487484
}
488485
489486
impl RawToSql for ~[u8] {
490487
fn raw_to_sql<W: Writer>(&self, w: &mut W) {
491488
w.write(self.as_slice())
492489
}
493-
494-
fn raw_size(&self) -> uint {
495-
self.len()
496-
}
497490
}
498491
499492
impl RawToSql for ~str {
500493
fn raw_to_sql<W: Writer>(&self, w: &mut W) {
501494
w.write(self.as_bytes())
502495
}
503-
504-
fn raw_size(&self) -> uint {
505-
self.len()
506-
}
507496
}
508497
509498
raw_to_impl!(i8, write_i8)
@@ -519,22 +508,67 @@ impl RawToSql for Timespec {
519508
+ self.nsec as i64 / NSEC_PER_USEC;
520509
w.write_be_i64(t);
521510
}
522-
523-
fn raw_size(&self) -> uint {
524-
mem::size_of::<i64>()
525-
}
526511
}
527512
528513
impl RawToSql for Uuid {
529514
fn raw_to_sql<W: Writer>(&self, w: &mut W) {
530515
w.write(self.to_bytes())
531516
}
532-
533-
fn raw_size(&self) -> uint {
534-
self.to_bytes().len()
535-
}
536517
}
537518
519+
macro_rules! to_range_impl(
520+
($($oid:ident)|+, $t:ty) => (
521+
impl RawToSql for Range<$t> {
522+
fn raw_to_sql<W: Writer>(&self, buf: &mut W) {
523+
let mut tag = 0;
524+
if self.is_empty() {
525+
tag |= RANGE_EMPTY;
526+
} else {
527+
match *self.lower() {
528+
None => tag |= RANGE_LOWER_UNBOUNDED,
529+
Some(RangeBound { type_: Inclusive, .. }) =>
530+
tag |= RANGE_LOWER_INCLUSIVE,
531+
_ => {}
532+
}
533+
match *self.upper() {
534+
None => tag |= RANGE_UPPER_UNBOUNDED,
535+
Some(RangeBound { type_: Inclusive, .. }) =>
536+
tag |= RANGE_UPPER_INCLUSIVE,
537+
_ => {}
538+
}
539+
}
540+
541+
buf.write_i8(tag);
542+
543+
match *self.lower() {
544+
Some(ref bound) => {
545+
let mut inner_buf = MemWriter::new();
546+
bound.value.raw_to_sql(&mut inner_buf);
547+
let inner_buf = inner_buf.inner();
548+
buf.write_be_i32(inner_buf.len() as i32);
549+
buf.write(inner_buf);
550+
}
551+
None => {}
552+
}
553+
match *self.upper() {
554+
Some(ref bound) => {
555+
let mut inner_buf = MemWriter::new();
556+
bound.value.raw_to_sql(&mut inner_buf);
557+
let inner_buf = inner_buf.inner();
558+
buf.write_be_i32(inner_buf.len() as i32);
559+
buf.write(inner_buf);
560+
}
561+
None => {}
562+
}
563+
}
564+
}
565+
)
566+
)
567+
568+
to_range_impl!(PgInt4Range, i32)
569+
to_range_impl!(PgInt8Range, i64)
570+
to_range_impl!(PgTsRange | PgTstzRange, Timespec)
571+
538572
macro_rules! to_option_impl(
539573
($($oid:pat)|+, $t:ty) => (
540574
impl ToSql for Option<$t> {
@@ -590,6 +624,9 @@ to_raw_to_impl!(PgInt4, i32)
590624
to_raw_to_impl!(PgInt8, i64)
591625
to_raw_to_impl!(PgFloat4, f32)
592626
to_raw_to_impl!(PgFloat8, f64)
627+
to_raw_to_impl!(PgInt4Range, Range<i32>)
628+
to_raw_to_impl!(PgInt8Range, Range<i64>)
629+
to_raw_to_impl!(PgTsRange | PgTstzRange, Range<Timespec>)
593630
594631
impl<'self> ToSql for &'self str {
595632
fn to_sql(&self, ty: &PostgresType) -> (Format, Option<~[u8]>) {
@@ -621,60 +658,6 @@ to_option_impl!(PgJson, Json)
621658
to_raw_to_impl!(PgTimestamp | PgTimestampTZ, Timespec)
622659
to_raw_to_impl!(PgUuid, Uuid)
623660
624-
macro_rules! to_range_impl(
625-
($($oid:ident)|+, $t:ty) => (
626-
impl ToSql for Range<$t> {
627-
fn to_sql(&self, ty: &PostgresType) -> (Format, Option<~[u8]>) {
628-
check_types!($($oid)|+, ty)
629-
let mut buf = MemWriter::new();
630-
631-
let mut tag = 0;
632-
if self.is_empty() {
633-
tag |= RANGE_EMPTY;
634-
} else {
635-
match *self.lower() {
636-
None => tag |= RANGE_LOWER_UNBOUNDED,
637-
Some(RangeBound { type_: Inclusive, .. }) =>
638-
tag |= RANGE_LOWER_INCLUSIVE,
639-
_ => {}
640-
}
641-
match *self.upper() {
642-
None => tag |= RANGE_UPPER_UNBOUNDED,
643-
Some(RangeBound { type_: Inclusive, .. }) =>
644-
tag |= RANGE_UPPER_INCLUSIVE,
645-
_ => {}
646-
}
647-
}
648-
649-
buf.write_i8(tag);
650-
651-
match *self.lower() {
652-
Some(ref bound) => {
653-
buf.write_be_i32(bound.value.raw_size() as i32);
654-
bound.value.raw_to_sql(&mut buf);
655-
}
656-
None => {}
657-
}
658-
match *self.upper() {
659-
Some(ref bound) => {
660-
buf.write_be_i32(bound.value.raw_size() as i32);
661-
bound.value.raw_to_sql(&mut buf);
662-
}
663-
None => {}
664-
}
665-
666-
(Binary, Some(buf.inner()))
667-
}
668-
}
669-
670-
to_option_impl!($($oid)|+, Range<$t>)
671-
)
672-
)
673-
674-
to_range_impl!(PgInt4Range, i32)
675-
to_range_impl!(PgInt8Range, i64)
676-
to_range_impl!(PgTsRange | PgTstzRange, Timespec)
677-
678661
macro_rules! to_array_impl(
679662
($($oid:ident)|+, $t:ty) => (
680663
impl ToSql for ArrayBase<Option<$t>> {
@@ -694,8 +677,11 @@ macro_rules! to_array_impl(
694677
for v in self.values() {
695678
match *v {
696679
Some(ref val) => {
697-
buf.write_be_i32(val.raw_size() as i32);
698-
val.raw_to_sql(&mut buf);
680+
let mut inner_buf = MemWriter::new();
681+
val.raw_to_sql(&mut inner_buf);
682+
let inner_buf = inner_buf.inner();
683+
buf.write_be_i32(inner_buf.len() as i32);
684+
buf.write(inner_buf);
699685
}
700686
None => buf.write_be_i32(-1)
701687
}
@@ -720,6 +706,7 @@ to_array_impl!(PgTimestampArray | PgTimestampTZArray, Timespec)
720706
to_array_impl!(PgFloat4Array, f32)
721707
to_array_impl!(PgFloat8Array, f64)
722708
to_array_impl!(PgUuidArray, Uuid)
709+
to_array_impl!(PgInt4RangeArray, Range<i32>)
723710
724711
impl<'self> ToSql for HashMap<~str, Option<~str>> {
725712
fn to_sql(&self, ty: &PostgresType) -> (Format, Option<~[u8]>) {

0 commit comments

Comments
 (0)