Skip to content

Commit

Permalink
Implement postgres::types::FromSql for TwkbPoint
Browse files Browse the repository at this point in the history
  • Loading branch information
pka committed Sep 26, 2016
1 parent d834d65 commit a4ad49c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 10 deletions.
63 changes: 55 additions & 8 deletions src/postgis.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use ewkb::{EwkbPoint,EwkbLineString,EwkbGeometryType};
use ewkb::{EwkbPoint, EwkbLineString, EwkbGeometryType};
use twkb::{TwkbGeom, TwkbPoint};
use std;
use std::io::prelude::*;
use postgres;
Expand Down Expand Up @@ -59,6 +60,28 @@ impl ToSql for EwkbLineString {
}
}

// --- TWKB ---

macro_rules! accepts_bytea {
() => (
fn accepts(ty: &Type) -> bool {
match ty {
&Type::Bytea => true,
_ => false
}
}
)
}


impl FromSql for TwkbPoint {
accepts_bytea!();
fn from_sql<R: Read>(ty: &Type, raw: &mut R, _ctx: &SessionInfo) -> postgres::Result<TwkbPoint> {
TwkbPoint::read_twkb(raw).map_err(|_| {let err: Box<std::error::Error + Sync + Send> = format!("cannot convert {} to POINT", ty).into(); postgres::error::Error::Conversion(err)})
}
}



#[cfg(test)]
mod tests {
Expand All @@ -68,6 +91,7 @@ mod tests {
use std::error::Error;
use geo::{self,Point, LineString};
use ewkb::{EwkbPoint,EwkbLineString};
use twkb::{TwkbPoint};

macro_rules! or_panic {
($e:expr) => (
Expand Down Expand Up @@ -145,17 +169,17 @@ mod tests {
#[ignore]
fn test_select() {
let conn = connect();
let result = or_panic!(conn.query("SELECT ST_GeomFromEWKT('POINT(10 -20)')", &[]));
let result = or_panic!(conn.query("SELECT ('POINT(10 -20)')::geometry", &[]));
let point = result.iter().map(|r| r.get::<_, EwkbPoint>(0)).last().unwrap();
assert_eq!(point.geom, Point::new(10.0, -20.0));
assert_eq!(point.srid, None);

let result = or_panic!(conn.query("SELECT ST_GeomFromEWKT('SRID=4326;POINT(10 -20)')", &[]));
let result = or_panic!(conn.query("SELECT 'SRID=4326;POINT(10 -20)'::geometry", &[]));
let point = result.iter().map(|r| r.get::<_, EwkbPoint>(0)).last().unwrap();
assert_eq!(point.geom, Point::new(10.0, -20.0));
assert_eq!(point.srid, Some(4326));

let result = or_panic!(conn.query("SELECT ST_GeomFromText('POINT EMPTY')", &[]));
let result = or_panic!(conn.query("SELECT 'POINT EMPTY'::geometry", &[]));
let point = result.iter().map(|r| r.get::<_, EwkbPoint>(0)).last().unwrap();
assert_eq!(&format!("{:?}", point.geom), "Point(Coordinate { x: NaN, y: NaN })");
assert!(point.geom.x().is_nan());
Expand All @@ -165,23 +189,46 @@ mod tests {
assert_eq!(&format!("{:?}", point), "Some(Err(Conversion(WasNull)))");

let p = |x, y| Point(geo::Coordinate { x: x, y: y });
let result = or_panic!(conn.query("SELECT ST_GeomFromEWKT('LINESTRING (10 -20, -0 -0.5)')", &[]));
let result = or_panic!(conn.query("SELECT ('LINESTRING (10 -20, -0 -0.5)')::geometry", &[]));
let line = result.iter().map(|r| r.get::<_, EwkbLineString>(0)).last().unwrap();
assert_eq!(line.geom, LineString(vec![p(10.0, -20.0), p(0., -0.5)]));
assert_eq!(line.srid, None);

let result = or_panic!(conn.query("SELECT ST_GeomFromEWKT('SRID=4326;LINESTRING (10 -20, -0 -0.5)')", &[]));
let result = or_panic!(conn.query("SELECT ('SRID=4326;LINESTRING (10 -20, -0 -0.5)')::geometry", &[]));
let line = result.iter().map(|r| r.get::<_, EwkbLineString>(0)).last().unwrap();
assert_eq!(line.geom, LineString(vec![p(10.0, -20.0), p(0., -0.5)]));
assert_eq!(line.srid, Some(4326));

let result = or_panic!(conn.query("SELECT ST_GeomFromText('LINESTRING EMPTY')", &[]));
let result = or_panic!(conn.query("SELECT 'LINESTRING EMPTY'::geometry", &[]));
let line = result.iter().map(|r| r.get::<_, EwkbLineString>(0)).last().unwrap();
assert_eq!(&format!("{:?}", line.geom), "LineString([])");
}

#[test]
#[ignore]
fn test_twkb() {
let conn = connect();
let result = or_panic!(conn.query("SELECT ST_AsTWKB('POINT(10 -20)'::geometry)", &[]));
let point = result.iter().map(|r| r.get::<_, TwkbPoint>(0)).last().unwrap();
assert_eq!(point.geom, Point::new(10.0, -20.0));

let result = or_panic!(conn.query("SELECT ST_AsTWKB('SRID=4326;POINT(10 -20)'::geometry)", &[]));
let point = result.iter().map(|r| r.get::<_, TwkbPoint>(0)).last().unwrap();
assert_eq!(point.geom, Point::new(10.0, -20.0));

let result = or_panic!(conn.query("SELECT ST_AsTWKB('POINT EMPTY'::geometry)", &[]));
let point = result.iter().map(|r| r.get::<_, TwkbPoint>(0)).last().unwrap();
assert_eq!(&format!("{:?}", point.geom), "Point(Coordinate { x: NaN, y: NaN })");
assert!(point.geom.x().is_nan());

let result = or_panic!(conn.query("SELECT ST_AsTWKB(NULL::geometry(Point))", &[]));
let point = result.iter().map(|r| r.get_opt::<_, TwkbPoint>(0)).last().unwrap();
assert_eq!(&format!("{:?}", point), "Some(Err(Conversion(WasNull)))");
}

#[test]
#[ignore]
#[allow(unused_imports,unused_variables)]
fn test_examples() {
use postgres::{Connection, SslMode};
//use postgis::EwkbLineString;
Expand All @@ -191,7 +238,7 @@ mod tests {
use ewkb::EwkbLineString;
let conn = connect();
or_panic!(conn.execute("CREATE TEMPORARY TABLE busline (route geometry(LineString))", &[]));
or_panic!(conn.execute("INSERT INTO busline (route) VALUES (ST_GeomFromEWKT('LINESTRING(10 -20, -0 -0.5)'))", &[]));
or_panic!(conn.execute("INSERT INTO busline (route) VALUES ('LINESTRING(10 -20, -0 -0.5)'::geometry)", &[]));
//

// conn ....
Expand Down
10 changes: 8 additions & 2 deletions src/twkb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub trait TwkbGeom: fmt::Debug + Sized {
let _deltam = try!(Self::read_int64(raw));
}
}
println!("{:?}", twkb_info);
Self::read_twkb_body(raw, twkb_info)
}

Expand Down Expand Up @@ -92,10 +93,11 @@ pub trait TwkbGeom: fmt::Debug + Sized {
}

fn varint64_to_f64(varint: u64, precision: i8) -> f64 {
println!("varint={}", Self::decode_zig_zag_64(varint) as f64);
if precision >= 0 {
(Self::decode_zig_zag_64(varint) as f64) / 10u8.pow(precision as u32) as f64
(Self::decode_zig_zag_64(varint) as f64) / 10u64.pow(precision as u32) as f64
} else {
(Self::decode_zig_zag_64(varint) as f64) * 10u8.pow(precision.abs() as u32) as f64
(Self::decode_zig_zag_64(varint) as f64) * 10u64.pow(precision.abs() as u32) as f64
}
}

Expand Down Expand Up @@ -156,4 +158,8 @@ fn test_twkb_to_geom() {
let twkb = hex_to_vec("0110"); // SELECT encode(ST_AsTWKB('POINT EMPTY'::geometry), 'hex')
let point = TwkbPoint::read_twkb(&mut twkb.as_slice()).unwrap();
assert_eq!(format!("{:?}", point.geom), "Point(Coordinate { x: NaN, y: NaN })");

let twkb = hex_to_vec("a10080897aff91f401"); // SELECT encode(ST_AsTWKB('SRID=4326;POINT(10 -20)'::geometry), 'hex')
let point = TwkbPoint::read_twkb(&mut twkb.as_slice()).unwrap();
assert_eq!(format!("{:?}", point.geom), "Point(Coordinate { x: 10, y: -20 })");
}

0 comments on commit a4ad49c

Please sign in to comment.