-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsql.go
116 lines (96 loc) · 2.48 KB
/
sql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package georm
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"strconv"
"github.com/twpayne/go-geom"
"github.com/twpayne/go-geom/encoding/ewkb"
"github.com/twpayne/go-geom/encoding/wkt"
)
var (
ErrUnexpectedGeometryType = errors.New("unexpected geometry type")
ErrUnexpectedValueType = errors.New("unexpected value type")
)
var SRID = 4326
type (
Geometry[T geom.T] struct{ Geom T }
Point = Geometry[*geom.Point]
LineString = Geometry[*geom.LineString]
Polygon = Geometry[*geom.Polygon]
MultiPoint = Geometry[*geom.MultiPoint]
MultiLineString = Geometry[*geom.MultiLineString]
MultiPolygon = Geometry[*geom.MultiPolygon]
GeometryCollection = Geometry[*geom.GeometryCollection]
)
func New[T geom.T](geom T) Geometry[T] { return Geometry[T]{geom} }
// Scan impl sql.Scanner
func (g *Geometry[T]) Scan(value interface{}) (err error) {
var (
wkb []byte
ok bool
)
switch v := value.(type) {
case string:
wkb, err = hex.DecodeString(v)
case []byte:
wkb = v
default:
return ErrUnexpectedGeometryType
}
if err != nil {
return err
}
geometryT, err := ewkb.Unmarshal(wkb)
if err != nil {
return err
}
g.Geom, ok = geometryT.(T)
if !ok {
return ErrUnexpectedValueType
}
return
}
// Value impl driver.Valuer
func (g Geometry[T]) Value() (driver.Value, error) {
if geom.T(g.Geom) == nil {
return nil, nil
}
sb := &bytes.Buffer{}
if err := ewkb.Write(sb, binary.LittleEndian, g.Geom); err != nil {
return nil, err
}
return hex.EncodeToString(sb.Bytes()), nil
}
// GormDataType impl schema.GormDataTypeInterface
func (g Geometry[T]) GormDataType() string {
srid := strconv.Itoa(SRID)
switch any(g.Geom).(type) {
case *geom.Point:
return "Geometry(Point, " + srid + ")"
case *geom.LineString:
return "Geometry(LineString, " + srid + ")"
case *geom.Polygon:
return "Geometry(Polygon, " + srid + ")"
case *geom.MultiPoint:
return "Geometry(MultiPoint, " + srid + ")"
case *geom.MultiLineString:
return "Geometry(MultiLineString, " + srid + ")"
case *geom.MultiPolygon:
return "Geometry(MultiPolygon, " + srid + ")"
case *geom.GeometryCollection:
return "Geometry(GeometryCollection, " + srid + ")"
default:
return "geometry"
}
}
// String returns geometry formatted using WKT format
func (g Geometry[T]) String() string {
if geomWkt, err := wkt.Marshal(g.Geom); err == nil {
return geomWkt
}
return fmt.Sprintf("cannot marshal geometry: %T", g.Geom)
}