Skip to content

Commit e0c3d2e

Browse files
committed
encoding/ewkb sql.Scanner and driver.Value
1 parent 2652fbd commit e0c3d2e

File tree

9 files changed

+1791
-238
lines changed

9 files changed

+1791
-238
lines changed

encoding/ewkb/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# encoding/ewkb [![Godoc Reference](https://pkg.go.dev/badge/github.com/paulmach/orb)](https://pkg.go.dev/github.com/paulmach/orb/encoding/ewkb)
22

3-
This package provides encoding and decoding of extended [WKB](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Format_variations)
3+
This package provides encoding and decoding of [extended WKB](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Format_variations)
44
data. This format includes the SRID in the data. If you don't need the SRID you can use the
55
[wkb](../wkb) package for a simpler interface.
66

encoding/ewkb/scanner.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package ewkb
2+
3+
import (
4+
"database/sql"
5+
"database/sql/driver"
6+
7+
"github.com/paulmach/orb"
8+
"github.com/paulmach/orb/encoding/internal/wkbcommon"
9+
)
10+
11+
var (
12+
_ sql.Scanner = &GeometryScanner{}
13+
_ driver.Value = value{}
14+
)
15+
16+
// GeometryScanner is a thing that can scan in sql query results.
17+
// It can be used as a scan destination:
18+
//
19+
// var s wkb.GeometryScanner
20+
// err := db.QueryRow("SELECT latlon FROM foo WHERE id=?", id).Scan(&s)
21+
// ...
22+
// if s.Valid {
23+
// // use s.Geometry
24+
// // use s.SRID
25+
// } else {
26+
// // NULL value
27+
// }
28+
type GeometryScanner struct {
29+
g interface{}
30+
SRID int
31+
Geometry orb.Geometry
32+
Valid bool // Valid is true if the geometry is not NULL
33+
}
34+
35+
// Scanner will return a GeometryScanner that can scan sql query results.
36+
// The geometryScanner.Geometry attribute will be set to the value.
37+
// If g is non-nil, it MUST be a pointer to an orb.Geometry
38+
// type like a Point or LineString. In that case the value will be written to
39+
// g and the Geometry attribute.
40+
//
41+
// var p orb.Point
42+
// err := db.QueryRow("SELECT latlon FROM foo WHERE id=?", id).Scan(wkb.Scanner(&p))
43+
// ...
44+
// // use p
45+
//
46+
// If the value may be null check Valid first:
47+
//
48+
// var point orb.Point
49+
// s := wkb.Scanner(&point)
50+
// err := db.QueryRow("SELECT latlon FROM foo WHERE id=?", id).Scan(s)
51+
// ...
52+
// if s.Valid {
53+
// // use p
54+
// } else {
55+
// // NULL value
56+
// }
57+
func Scanner(g interface{}) *GeometryScanner {
58+
return &GeometryScanner{g: g}
59+
}
60+
61+
// Scan will scan the input []byte data into a geometry.
62+
// This could be into the orb geometry type pointer or, if nil,
63+
// the scanner.Geometry attribute.
64+
func (s *GeometryScanner) Scan(d interface{}) error {
65+
s.Geometry = nil
66+
s.Valid = false
67+
68+
g, srid, valid, err := wkbcommon.Scan(s.g, d)
69+
if err != nil {
70+
return mapCommonError(err)
71+
}
72+
73+
s.Geometry = g
74+
s.SRID = srid
75+
s.Valid = valid
76+
77+
return nil
78+
}
79+
80+
type value struct {
81+
srid int
82+
v orb.Geometry
83+
}
84+
85+
// Value will create a driver.Valuer that will EWKB the geometry into the database query.
86+
//
87+
// db.Exec("INSERT INTO table (point_column) VALUES (?)", ewkb.Value(p, 4326))
88+
func Value(g orb.Geometry, srid int) driver.Valuer {
89+
return value{srid: srid, v: g}
90+
91+
}
92+
93+
func (v value) Value() (driver.Value, error) {
94+
val, err := Marshal(v.v, v.srid)
95+
if val == nil {
96+
return nil, err
97+
}
98+
return val, err
99+
}

0 commit comments

Comments
 (0)