@@ -3,6 +3,7 @@ package ewkb
33import (
44 "database/sql"
55 "database/sql/driver"
6+ "encoding/binary"
67
78 "github.com/paulmach/orb"
89 "github.com/paulmach/orb/encoding/internal/wkbcommon"
@@ -26,10 +27,11 @@ var (
2627// // NULL value
2728// }
2829type GeometryScanner struct {
29- g interface {}
30- SRID int
31- Geometry orb.Geometry
32- Valid bool // Valid is true if the geometry is not NULL
30+ sridInPrefix bool
31+ g interface {}
32+ SRID int
33+ Geometry orb.Geometry
34+ Valid bool // Valid is true if the geometry is not NULL
3335}
3436
3537// Scanner will return a GeometryScanner that can scan sql query results.
@@ -58,18 +60,63 @@ func Scanner(g interface{}) *GeometryScanner {
5860 return & GeometryScanner {g : g }
5961}
6062
63+ // ScannerPrefixSRID will scan ewkb data were the SRID is in the first 4 bytes of the data.
64+ // Databases like mysql/mariadb use this as their raw format. This method should only be used when
65+ // working with such a database.
66+ //
67+ // var p orb.Point
68+ // err := db.QueryRow("SELECT latlon FROM foo WHERE id=?", id).Scan(wkb.PrefixSRIDScanner(&p))
69+ //
70+ // However, it is recommended to covert to wkb explicitly using something like:
71+ //
72+ // var srid int
73+ // var p orb.Point
74+ // err := db.QueryRow("SELECT ST_SRID(latlon), ST_AsBinary(latlon) FROM foo WHERE id=?", id).
75+ // Scan(&srid, wkb.Scanner(&p))
76+ func ScannerPrefixSRID (g interface {}) * GeometryScanner {
77+ return & GeometryScanner {sridInPrefix : true , g : g }
78+ }
79+
6180// Scan will scan the input []byte data into a geometry.
6281// This could be into the orb geometry type pointer or, if nil,
6382// the scanner.Geometry attribute.
6483func (s * GeometryScanner ) Scan (d interface {}) error {
6584 s .Geometry = nil
6685 s .Valid = false
6786
68- g , srid , valid , err := wkbcommon .Scan (s .g , d )
87+ var (
88+ srid int
89+ data interface {}
90+ )
91+
92+ data = d
93+ if s .sridInPrefix {
94+ raw , ok := d .([]byte )
95+ if ! ok {
96+ return ErrUnsupportedDataType
97+ }
98+
99+ if raw == nil {
100+ return nil
101+ }
102+
103+ if len (raw ) < 5 {
104+ return ErrNotEWKB
105+ }
106+
107+ srid = int (binary .LittleEndian .Uint32 (raw ))
108+ data = raw [4 :]
109+ }
110+
111+ g , embeddedSRID , valid , err := wkbcommon .Scan (s .g , data )
69112 if err != nil {
70113 return mapCommonError (err )
71114 }
72115
116+ if embeddedSRID != 0 {
117+ srid = embeddedSRID
118+ }
119+
73120 s .Geometry = g
74121 s .SRID = srid
75122 s .Valid = valid
0 commit comments