Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geography point support #7

Open
Boscop opened this issue Aug 30, 2018 · 11 comments
Open

Geography point support #7

Boscop opened this issue Aug 30, 2018 · 11 comments

Comments

@Boscop
Copy link

Boscop commented Aug 30, 2018

I tried to use it with geography point type geography(point, 4326) not null in postgres and PgPoint in my model struct, but it's not deserializing the values correctly:

When I insert

ST_SetSRID(ST_MakePoint(13.409779,52.520645), 4326)::geography

and then print it in my Rust executable, it prints:

PgPoint(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007746818039357731, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013770074297002852)

:/

@Boscop
Copy link
Author

Boscop commented Aug 30, 2018

Btw, this is how it looks in psql:

geo=# select loc from users;
                        loc                         
----------------------------------------------------
 0101000020E6100000D82C978DCED12A40B8E9CF7EA4424A40
(1 row)

geo=# select ST_AsText(loc) from users;
         st_astext          
----------------------------
 POINT(13.409779 52.520645)
(1 row)

geo=# select ST_AsEWKT(loc) from users;
              st_asewkt               
--------------------------------------
 SRID=4326;POINT(13.409779 52.520645)
(1 row)

@Boscop
Copy link
Author

Boscop commented Aug 30, 2018

It's probably trying to deserialize the hex WKB as 2 f64:
https://github.com/ThinkAlexandria/diesel_geometry/blob/master/src/pg/types/geometric.rs#L23-L24

Looking at this
https://en.wikipedia.org/wiki/Well-known_text#Well-known_binary
and this:
http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt#L159
makes it clear:
In my case above, first byte is 1 so byteOrder is little endian, then wkbType is 0x20000001 which is wkbPoint + wkbSRID, then SRID is 0x10E6 which is 4326 and then come the longitude (x) and latitude (y).

@Boscop
Copy link
Author

Boscop commented Aug 30, 2018

This crate already provides a EWKB decoder for geography Point types (with SRID):
https://github.com/andelf/rust-postgis/blob/5cf434b9c44783978d59a3359ae07061fce9da76/src/ewkb.rs#L341
We could just re-use that.. (It also uses MIT License)

The wkb crate doesn't seem to support it though:
https://github.com/rory/rust-wkb/blob/master/src/lib.rs#L170

@Boscop
Copy link
Author

Boscop commented Sep 2, 2018

Yes, it's trying to interpret the first 8 bytes as the first f64 and the next 8 bytes as the second coordinate:
http://www.binaryconvert.com/result_double.html?hexadecimal=0101000020E61000
0x0101000020E61000 -> 7.74681803935773114768989259805E-304
which matches the "PgPoint" that it returned above.

So now we know how to parse it correctly, but how should we serialize it?
EWKB strings can't be used as literals in query expressions..

This works:

cast('0101000020E6100000D82C978DCED12A40B8E9CF7EA4424A40' as geography)

This also:

cast('0101000020E6100000D82C978DCED12A40B8E9CF7EA4424A40' as geometry)

https://gis.stackexchange.com/a/210400

But there's probably a better way..

@Boscop
Copy link
Author

Boscop commented Sep 21, 2018

@YetAnotherMinion do you have an idea what's the right way to serialize the EWKB?

@YetAnotherMinion
Copy link
Member

I understand how to do the serialization. Rust-postgis code is pretty clear to me.

I don't think that both geometry and geography should live in the same crate. There is some irreducible complexity around diesel_cli's automatic schema generation where both types are called Point, but beyond that corner case, I don't see code sharing between the two domains.

I think sister crates are the best way to allow development by two relatively independent groups of users.

I will create a diesel_geography crate using this one as a template because I like keeping the file layout close to diesel's internal layout.

@Boscop
Copy link
Author

Boscop commented Sep 24, 2018

@YetAnotherMinion Thanks, I'm looking forward to using the diesel_geography crate for some uni projects :)
For now, I'd basically only need support for columns of type geography(point, 4326), I can use raw string queries for all the postgis functions.
I'm also interested in contributing to that crate, e.g. adding support for the postgis functions that I'm using, like ST_DWithin, ST_Distance etc.

@YetAnotherMinion
Copy link
Member

YetAnotherMinion commented Oct 17, 2018

@Boscop Update: I am now fixing compiler errors in rust-postgis 0.6 to be able to use their postgres::types::FromSql impl.

The errors only appear in nightly and not stable or beta. I am going to check if this is a compiler regression. The error is consistent with trait bounds not being applied.

@Boscop
Copy link
Author

Boscop commented Nov 18, 2018

@YetAnotherMinion Any update on this? :)
I'm looking forward to use & contribute to the diesel_geography crate..

@Boscop
Copy link
Author

Boscop commented Nov 24, 2018

I implemented FromSql and ToSql for geography points (using postgis) here:
https://crates.io/crates/diesel-geography
I'll add more types & functions over time, as I need them..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants