Skip to content

Commit

Permalink
Add DB module
Browse files Browse the repository at this point in the history
  • Loading branch information
amauryt committed May 24, 2024
1 parent 35020f3 commit f7097a5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,13 +383,16 @@ Given that the extension is optional, you could also implement your own (Geo)JSO

## Geometries on a Database

This library can be used to communicate with any system that implements WKB, including many database engines. Below is a full example of using it to receive and transmit geometry data from and to PostGIS using [crystal-pg](https://github.com/will/crystal-pg), the Postgres driver for [crystal-db](https://github.com/crystal-lang/crystal-db).
This library can be used to communicate with any system that implements WKB, including many database engines. In that case, you can either work at the bytes level doing the conversion yourself, or use converters for `WKB::Object` and all its descendants for easier reading with `DB::Serializable` from `crystal-db`.

Below is a full example of using it to receive and transmit geometry data from and to PostGIS using [crystal-pg](https://github.com/will/crystal-pg), the Postgres driver for [crystal-db](https://github.com/crystal-lang/crystal-db).

```crystal
require "db"
require "pg"
require "wkb"
require "wkb/geojson" # Needed for GeoJSON support
require "wkb/geojson" # For GeoJSON support
require "wkb/db" # For `DB::Serializable` support. Must be loaded after "db"!
decoder = WKB::BinDecoder.new
encoder = WKB::BinEncoder.new(WKB::Flavor::Ext) # or `ExtSRID` if you use SRID
Expand All @@ -409,6 +412,15 @@ polygon_json = <<-JSON
}
JSON
class Place
include DB::Serializable
property name : String
@[DB::Field(converter: WKB::DB::PointConverter)]
property location : WKB::Point
end
DB.open("postgres://user:password@host:port/db_name") do |db|
point_bytes = db.scalar("SELECT 'POINT(1 2 3)'::GEOMETRY;").as(Bytes)
point = decoder.decode(point_bytes).as(WKB::Point)
Expand All @@ -424,6 +436,10 @@ DB.open("postgres://user:password@host:port/db_name") do |db|
polygon_bytes = encoder.encode(polygon)
polygon_perimeter = db.scalar("SELECT ST_Perimeter($1::GEOMETRY)", polygon_bytes).as(Float64)
polygon_perimeter # => 114.35571426165451
query_str = "SELECT 'Neverland' AS name, 'POINT(1 2)'::GEOMETRY AS location"
places = Place.from_rs(db.query(query_str))
places.first.location.x # => 1.0
end
```

Expand Down
25 changes: 25 additions & 0 deletions src/wkb/db.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require "./bin_decoder"

module WKB
module DB
{% for kind in %w[
Object
Geometry
Point
LineString
Polygon
MultiPoint
MultiLineString
MultiPolygon
GeometryCollection
] %}
module {{kind.id}}Converter
@@decoder = WKB::BinDecoder.new

def self.from_rs(rs : ::DB::ResultSet)
@@decoder.decode(rs.read(Bytes)).as(WKB::{{kind.id}})
end
end
{% end %}
end
end

0 comments on commit f7097a5

Please sign in to comment.