Documentation
¶
Overview ¶
Package postgis makes PostGIS type-safe without hiding it.
It is opt-in. A project that does not import it never sees a spatial API, and the root ORM knows nothing about geometry — everything here composes through the one extension boundary that package exposes, so there is no second query compiler and no second expression model.
Two distinctions run through the whole package and are never blurred:
geometry Cartesian, in whatever units the SRID's coordinate system uses geography on the spheroid, with distances and lengths in metres
They are different PostgreSQL types with different index behaviour and different answers, so they are different Go types here. Converting between them is something you write, not something that happens to you.
the shape Point, LineString, Polygon, and the multi forms the SRID which coordinate system the numbers are in
Both travel with the value and with the column, because losing either is how a query comes to compare metres with degrees and get a number back.
Index ¶
- Constants
- Variables
- func Collect[E any](g GeomExpr[E]) orm.Agg[E, *Geometry]
- func DimConst(d Dim) string
- func Extent[E any](g GeomExpr[E]) orm.Agg[E, *Box2D]
- func Extent3D[E any](g GeomExpr[E]) orm.Agg[E, *Box3D]
- func KindConst(k Kind) string
- func Register(ctx context.Context, conn *pgx.Conn) error
- func RegisterIfPresent(ctx context.Context, conn *pgx.Conn) (bool, error)
- func UnionAgg[E any](g GeomExpr[E]) orm.Agg[E, *Geometry]
- type Box2D
- type Box3D
- type Coord
- type Dim
- type Family
- type GeogCol
- type GeogExpr
- func ComposeGeog[E any](g GeogExpr[E]) GeogExpr[orm.Composed]
- func GeogFromExpr[E any](v orm.Selectable[E, Geography], mod TypeMod) GeogExpr[E]
- func GeogFromExprNull[E any](v orm.Optional[E, *Geography], mod TypeMod) GeogExpr[E]
- func GeogFromText[E any](wkt string) GeogExpr[E]
- func GeogValue[E any](g Geography) GeogExpr[E]
- func OfGeog[E any](c interface{ ... }) GeogExpr[orm.Composed]
- func (g GeogExpr[E]) Area() orm.Value[E, float64]
- func (g GeogExpr[E]) AreaNull() orm.Value[E, *float64]
- func (g GeogExpr[E]) AsEWKT() orm.Value[E, string]
- func (g GeogExpr[E]) AsGeoJSON() orm.Value[E, string]
- func (g GeogExpr[E]) AsGeoJSONNull() orm.Value[E, *string]
- func (g GeogExpr[E]) AsGeometry() GeomExpr[E]
- func (g GeogExpr[E]) AsText() orm.Value[E, string]
- func (g GeogExpr[E]) AsTextNull() orm.Value[E, *string]
- func (g GeogExpr[E]) BBoxIntersects(other GeogExpr[E]) orm.Predicate[E]
- func (g GeogExpr[E]) BufferMetres(metres float64) GeogExpr[E]
- func (g GeogExpr[E]) CoveredBy(other GeogExpr[E]) orm.Predicate[E]
- func (g GeogExpr[E]) Covers(other GeogExpr[E]) orm.Predicate[E]
- func (g GeogExpr[E]) DWithin(other GeogExpr[E], metres float64) orm.Predicate[E]
- func (g GeogExpr[E]) DeclaredSRID() int32
- func (g GeogExpr[E]) Distance(other GeogExpr[E]) orm.Value[E, float64]
- func (g GeogExpr[E]) DistanceNull(other GeogExpr[E]) orm.Value[E, *float64]
- func (g GeogExpr[E]) Intersects(other GeogExpr[E]) orm.Predicate[E]
- func (g GeogExpr[E]) KNNDistance(other GeogExpr[E]) orm.Value[E, float64]
- func (g GeogExpr[E]) Length() orm.Value[E, float64]
- func (g GeogExpr[E]) LengthNull() orm.Value[E, *float64]
- func (g GeogExpr[E]) Nullable() bool
- func (g GeogExpr[E]) Perimeter() orm.Value[E, float64]
- func (g GeogExpr[E]) SRID() orm.Value[E, int32]
- func (g GeogExpr[E]) Value() orm.Value[E, Geography]
- func (g GeogExpr[E]) ValueNull() orm.Value[E, *Geography]
- type Geography
- func (g Geography) AppendEWKB(dst []byte) []byte
- func (g Geography) AsGeometry() Geometry
- func (g Geography) Coords() []Coord
- func (g Geography) Dim() Dim
- func (g Geography) EWKB() []byte
- func (g Geography) Equal(other Geography) bool
- func (g Geography) Geometries() []Geometry
- func (g Geography) IsEmpty() bool
- func (g Geography) Kind() Kind
- func (g Geography) NumPoints() int
- func (g Geography) SRID() int32
- func (g Geography) String() string
- type GeomCol
- type GeomExpr
- func Compose[E any](g GeomExpr[E]) GeomExpr[orm.Composed]
- func FromExpr[E any](v orm.Selectable[E, Geometry], mod TypeMod) GeomExpr[E]
- func FromExprNull[E any](v orm.Optional[E, *Geometry], mod TypeMod) GeomExpr[E]
- func GeomFromEWKB[E any](ewkb []byte) GeomExpr[E]
- func GeomFromGeoJSON[E any](doc string) GeomExpr[E]
- func GeomFromGeoJSONExpr[E any](doc orm.Selectable[E, string]) GeomExpr[E]
- func GeomFromText[E any](wkt string, srid int32) GeomExpr[E]
- func GeomFromTextExpr[E any](wkt orm.Selectable[E, string], srid int32) GeomExpr[E]
- func MakeEnvelope[E any](minX, minY, maxX, maxY float64, srid int32) GeomExpr[E]
- func MakePoint[E any](x, y orm.Selectable[E, float64]) GeomExpr[E]
- func MakePointM[E any](x, y, m orm.Selectable[E, float64]) GeomExpr[E]
- func MakePointZ[E any](x, y, z orm.Selectable[E, float64]) GeomExpr[E]
- func Of[E any](c interface{ ... }) GeomExpr[orm.Composed]
- func Value[E any](g Geometry) GeomExpr[E]
- func (g GeomExpr[E]) Area() orm.Value[E, float64]
- func (g GeomExpr[E]) AreaNull() orm.Value[E, *float64]
- func (g GeomExpr[E]) AsBinary() orm.Value[E, []byte]
- func (g GeomExpr[E]) AsBinaryNull() orm.Value[E, *[]byte]
- func (g GeomExpr[E]) AsEWKB() orm.Value[E, []byte]
- func (g GeomExpr[E]) AsEWKBNull() orm.Value[E, *[]byte]
- func (g GeomExpr[E]) AsEWKT() orm.Value[E, string]
- func (g GeomExpr[E]) AsEWKTNull() orm.Value[E, *string]
- func (g GeomExpr[E]) AsGeoJSON() orm.Value[E, string]
- func (g GeomExpr[E]) AsGeoJSONNull() orm.Value[E, *string]
- func (g GeomExpr[E]) AsGeography() GeogExpr[E]
- func (g GeomExpr[E]) AsText() orm.Value[E, string]
- func (g GeomExpr[E]) AsTextNull() orm.Value[E, *string]
- func (g GeomExpr[E]) Azimuth(other GeomExpr[E]) orm.Value[E, *float64]
- func (g GeomExpr[E]) BBoxContains(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) BBoxDistance(other GeomExpr[E]) orm.Value[E, float64]
- func (g GeomExpr[E]) BBoxIntersects(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) BBoxSame(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) BBoxWithin(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Boundary() GeomExpr[E]
- func (g GeomExpr[E]) Buffer(distance float64) GeomExpr[E]
- func (g GeomExpr[E]) Centroid() GeomExpr[E]
- func (g GeomExpr[E]) CollectionExtract(k Kind) GeomExpr[E]
- func (g GeomExpr[E]) Contains(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) ContainsProperly(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) ConvexHull() GeomExpr[E]
- func (g GeomExpr[E]) CoordDim() orm.Value[E, int16]
- func (g GeomExpr[E]) CoveredBy(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Covers(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Crosses(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) DFullyWithin(other GeomExpr[E], distance float64) orm.Predicate[E]
- func (g GeomExpr[E]) DWithin(other GeomExpr[E], distance float64) orm.Predicate[E]
- func (g GeomExpr[E]) DeclaredDim() Dim
- func (g GeomExpr[E]) DeclaredKind() Kind
- func (g GeomExpr[E]) DeclaredSRID() int32
- func (g GeomExpr[E]) Difference(other GeomExpr[E]) GeomExpr[E]
- func (g GeomExpr[E]) Dimension() orm.Value[E, int32]
- func (g GeomExpr[E]) Disjoint(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Distance(other GeomExpr[E]) orm.Value[E, float64]
- func (g GeomExpr[E]) DistanceNull(other GeomExpr[E]) orm.Value[E, *float64]
- func (g GeomExpr[E]) Envelope() GeomExpr[E]
- func (g GeomExpr[E]) EqualsGeom(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Force2D() GeomExpr[E]
- func (g GeomExpr[E]) Force3D() GeomExpr[E]
- func (g GeomExpr[E]) GeometryType() orm.Value[E, string]
- func (g GeomExpr[E]) Intersection(other GeomExpr[E]) GeomExpr[E]
- func (g GeomExpr[E]) Intersects(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) IsEmptyGeom() orm.Predicate[E]
- func (g GeomExpr[E]) IsSimple() orm.Predicate[E]
- func (g GeomExpr[E]) IsValid() orm.Predicate[E]
- func (g GeomExpr[E]) IsValidReason() orm.Value[E, string]
- func (g GeomExpr[E]) IsValidReasonNull() orm.Value[E, *string]
- func (g GeomExpr[E]) KNNDistance(other GeomExpr[E]) orm.Value[E, float64]
- func (g GeomExpr[E]) Length() orm.Value[E, float64]
- func (g GeomExpr[E]) LengthNull() orm.Value[E, *float64]
- func (g GeomExpr[E]) M() orm.Value[E, *float64]
- func (g GeomExpr[E]) MakeValid() GeomExpr[E]
- func (g GeomExpr[E]) MaxDistance(other GeomExpr[E]) orm.Value[E, float64]
- func (g GeomExpr[E]) Multi() GeomExpr[E]
- func (g GeomExpr[E]) Nullable() bool
- func (g GeomExpr[E]) NumGeometries() orm.Value[E, int32]
- func (g GeomExpr[E]) NumPoints() orm.Value[E, int32]
- func (g GeomExpr[E]) Overlaps(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Perimeter() orm.Value[E, float64]
- func (g GeomExpr[E]) PerimeterNull() orm.Value[E, *float64]
- func (g GeomExpr[E]) PointOnSurface() GeomExpr[E]
- func (g GeomExpr[E]) Relate(other GeomExpr[E], pattern string) orm.Predicate[E]
- func (g GeomExpr[E]) SRID() orm.Value[E, int32]
- func (g GeomExpr[E]) SetSRID(srid int32) GeomExpr[E]
- func (g GeomExpr[E]) Simplify(tolerance float64) GeomExpr[E]
- func (g GeomExpr[E]) SimplifyPreserveTopology(tolerance float64) GeomExpr[E]
- func (g GeomExpr[E]) SymDifference(other GeomExpr[E]) GeomExpr[E]
- func (g GeomExpr[E]) Touches(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) Transform(srid int32) GeomExpr[E]
- func (g GeomExpr[E]) Union(other GeomExpr[E]) GeomExpr[E]
- func (g GeomExpr[E]) Value() orm.Value[E, Geometry]
- func (g GeomExpr[E]) ValueNull() orm.Value[E, *Geometry]
- func (g GeomExpr[E]) Within(other GeomExpr[E]) orm.Predicate[E]
- func (g GeomExpr[E]) X() orm.Value[E, *float64]
- func (g GeomExpr[E]) Y() orm.Value[E, *float64]
- func (g GeomExpr[E]) Z() orm.Value[E, *float64]
- type Geometry
- func DecodeEWKB(b []byte) (Geometry, error)
- func EmptyPoint(srid int32) Geometry
- func NewCollection(srid int32, members ...Geometry) (Geometry, error)
- func NewLineString(srid int32, dim Dim, cs ...Coord) Geometry
- func NewMultiLineString(srid int32, dim Dim, lines ...[]Coord) Geometry
- func NewMultiPoint(srid int32, dim Dim, cs ...Coord) Geometry
- func NewMultiPolygon(srid int32, dim Dim, polygons ...[][]Coord) Geometry
- func NewPoint(srid int32, x, y float64) Geometry
- func NewPointM(srid int32, x, y, m float64) Geometry
- func NewPointZ(srid int32, x, y, z float64) Geometry
- func NewPointZM(srid int32, x, y, z, m float64) Geometry
- func NewPolygon(srid int32, dim Dim, rings ...[]Coord) Geometry
- func (g Geometry) AppendEWKB(dst []byte) []byte
- func (g Geometry) AsGeography() (Geography, error)
- func (g Geometry) Coords() []Coord
- func (g Geometry) Dim() Dim
- func (g Geometry) EWKB() []byte
- func (g Geometry) Equal(other Geometry) bool
- func (g Geometry) Geometries() []Geometry
- func (g Geometry) IsEmpty() bool
- func (g Geometry) Kind() Kind
- func (g Geometry) NumPoints() int
- func (g Geometry) SRID() int32
- func (g Geometry) String() string
- func (g Geometry) WithSRID(srid int32) Geometry
- type Kind
- type NotInstalledError
- type NullGeogCol
- func (c NullGeogCol[E]) Area() orm.Value[E, *float64]
- func (c NullGeogCol[E]) Dim() Dim
- func (c NullGeogCol[E]) Expr() GeogExpr[E]
- func (c NullGeogCol[E]) Kind() Kind
- func (c NullGeogCol[E]) Length() orm.Value[E, *float64]
- func (c NullGeogCol[E]) SRID() int32
- func (c NullGeogCol[E]) TypeMod() TypeMod
- type NullGeomCol
- func (c NullGeomCol[E]) Area() orm.Value[E, *float64]
- func (c NullGeomCol[E]) Dim() Dim
- func (c NullGeomCol[E]) Expr() GeomExpr[E]
- func (c NullGeomCol[E]) Kind() Kind
- func (c NullGeomCol[E]) Length() orm.Value[E, *float64]
- func (c NullGeomCol[E]) SRID() int32
- func (c NullGeomCol[E]) TypeMod() TypeMod
- type TypeMod
Constants ¶
const UnknownSRID int32 = 0
UnknownSRID is PostGIS's "no spatial reference": SRID 0.
It is not 4326. A geometry that never had an SRID assigned is in an unspecified coordinate system, and treating it as longitude and latitude because that is the common case is how coordinates end up in the wrong place on a map. Nothing here infers one.
Variables ¶
var ErrShortEWKB = errors.New("postgis: the geometry data ends in the middle of a value")
ErrShortEWKB reports an encoding that ended before the geometry it described did.
Functions ¶
func Collect ¶
Collect gathers the group's geometries into one multi geometry or collection, without dissolving the boundaries between them.
It is much cheaper than UnionAgg and answers a different question: Collect puts a hundred polygons in one value, Union merges them into the shape they jointly cover. Reach for Collect when the parts still matter.
The result's shape depends on what went in — points give a MultiPoint, mixed shapes give a GeometryCollection — so it claims none.
func Extent ¶
Extent is the bounding box of every geometry in the group.
It returns a Box2D and not a geometry, because that is what PostGIS returns: ST_Extent's result type is box2d, a type with its own text form, no SRID and no binary send function. Typing it as a geometry would put the EWKB codec in front of bytes that are not EWKB.
The box carries no coordinate system. Use Box2D.Geometry with the SRID the group was in when a geometry is what is wanted.
func Register ¶
Register teaches a connection the PostGIS types.
Wire it into a pool so every connection is taught once:
cfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
return err
}
cfg.AfterConnect = postgis.Register
pool, err := pgxpool.NewWithConfig(ctx, cfg)
A project that also has generated enum registration composes the two:
cfg.AfterConnect = func(ctx context.Context, c *pgx.Conn) error {
if err := domain.RegisterTypes(ctx, c); err != nil {
return err
}
return postgis.Register(ctx, c)
}
It reports an error when PostGIS is not installed in the database, because a program that registers spatial types and then finds none is a program whose next query would fail with something much less specific.
func RegisterIfPresent ¶
RegisterIfPresent is Register for a program that runs against databases with and without PostGIS.
It reports whether the extension was found. When it was not, the connection is left exactly as it was and no error is returned — which is the right shape for an application whose spatial features are optional, and the wrong shape for one whose queries are all spatial.
func UnionAgg ¶
UnionAgg merges the group's geometries into the single shape they cover, dissolving shared boundaries.
This is the aggregate ST_Union, which is a different function from the two-argument GeomExpr.Union despite the shared name — PostgreSQL tells them apart by arity and this package tells them apart by which type they hang on.
It is expensive. Merging a large group is a real geometric computation, and a query that does it per row of a join will be slow for reasons no index fixes.
Types ¶
type Box2D ¶
type Box2D struct {
// The corners of the rectangle, in the reference system of whatever
// produced it. Min is the lower-left, Max the upper-right.
MinX, MinY float64
MaxX, MaxY float64
// Valid distinguishes a box from the absence of one. ST_Extent over no rows
// is NULL, and a zero-size box at the origin is a different answer.
Valid bool
}
Box2D is a rectangle in the plane, as PostGIS's box2d.
func (Box2D) Geometry ¶
Geometry returns the box as a closed polygon in the given SRID.
The SRID is an argument because a box does not carry one — see the note at the top of this file. A degenerate box, one with no width or no height, still produces the five-vertex ring PostGIS's own ST_Envelope would for a line or a point, rather than a shape that is not a polygon.
type Box3D ¶
type Box3D struct {
// The corners of the box, in the reference system of whatever produced it.
MinX, MinY, MinZ float64
MaxX, MaxY, MaxZ float64
// Valid distinguishes a box from the absence of one: ST_3DExtent over no
// rows is NULL, and a zero-size box at the origin is a different answer.
Valid bool
}
Box3D is a box in space, as PostGIS's box3d.
type Coord ¶
type Coord struct {
// X and Y are the horizontal ordinates — longitude and latitude in a
// geographic reference system, easting and northing in a projected one.
// Which they are is decided by the SRID, not by this type.
//
// Z is elevation and M is a measure: a per-vertex value, most often a
// distance along a route or a timestamp. Both are zero when the geometry
// does not carry them, which is why the dimension is recorded separately
// rather than inferred from these being zero.
X, Y, Z, M float64
}
Coord is one position.
Z and M are meaningful only when the geometry's dimensionality says so, which is why they are read through the geometry rather than tested for zero: 0 is a legitimate elevation.
type Dim ¶
type Dim uint8
Dim is a geometry's coordinate dimensionality.
PostGIS stores four: the plain XY, XY with a Z ordinate, XY with a measure, and both. They are part of the type — geometry(PointZ,4326) is not geometry(Point,4326) — so nothing here drops an ordinate to make a value fit.
const ( // XY is two ordinates, which is what an unqualified geometry has. XY Dim = iota // XYZ adds a Z ordinate. XYZ // XYM adds a measure. XYM // XYZM has both. XYZM )
The dimensionalities PostGIS stores.
type Family ¶
type Family uint8
Family is which of the two PostgreSQL spatial types a column has.
const ( // NotSpatial is the zero value: this is not a spatial type at all. NotSpatial Family = iota // FamilyGeometry is PostGIS's geometry: Cartesian, in the SRID's units. FamilyGeometry // FamilyGeography is PostGIS's geography: on the spheroid, in metres. FamilyGeography )
The spatial storage families.
type GeogCol ¶
GeogCol is a NOT NULL geography column of entity E.
func NewGeogCol ¶
NewGeogCol returns a geography column descriptor.
func (GeogCol[E]) Kind ¶
Kind reports the shape the column's type constrains it to, or zero when its type accepts any.
func (GeogCol[E]) SRID ¶
SRID reports the coordinate system the column is declared in, or UnknownSRID when its type does not constrain one.
type GeogExpr ¶
type GeogExpr[E any] struct { // contains filtered or unexported fields }
GeogExpr is a geography-valued expression over entity E.
It is a separate type from GeomExpr and not a flag on it, so that handing a geography to a function that measures in the plane does not compile. The mistake it prevents is the expensive one: ST_Distance over geometry(4326) returns degrees, which is a number, which looks like an answer.
func ComposeGeog ¶
ComposeGeog drops the entity tag from a geography expression.
func GeogFromExpr ¶
GeogFromExpr is FromExpr for a geography.
func GeogFromExprNull ¶
GeogFromExprNull is GeogFromExpr for a projected geography that can be NULL.
func GeogFromText ¶
GeogFromText parses WKT or EWKT into a geography.
PostGIS's geography parser takes the SRID from an EWKT prefix and otherwise assumes 4326, which is the one place in this package a default coordinate system is not this package's choice — it is the function's own documented behaviour, and the expression records 4326 so that later checks see what PostGIS will see.
func (GeogExpr[E]) AreaNull ¶
AreaNull is GeogExpr.Area over a geography that can be NULL.
func (GeogExpr[E]) AsGeoJSON ¶
AsGeoJSON renders the geography as a GeoJSON geometry object, as text.
func (GeogExpr[E]) AsGeoJSONNull ¶
AsGeoJSONNull is GeogExpr.AsGeoJSON over a geography that can be NULL.
func (GeogExpr[E]) AsGeometry ¶
AsGeometry casts a geography expression to geometry, so that the plane operations apply. Distances over the result are in the SRID's units.
func (GeogExpr[E]) AsTextNull ¶
AsTextNull is GeogExpr.AsText over a geography that can be NULL.
func (GeogExpr[E]) BBoxIntersects ¶
BBoxIntersects builds the && operator over the geographies' bounding boxes on the sphere.
func (GeogExpr[E]) BufferMetres ¶
BufferMetres grows a geography by distance in metres.
PostGIS returns a geography here, having done the work on the spheroid, which is what makes "everything within 500 metres" a question with one answer rather than one per latitude.
func (GeogExpr[E]) CoveredBy ¶
CoveredBy reports whether no point of the receiver lies outside the other geography.
func (GeogExpr[E]) Covers ¶
Covers reports whether no point of the other geography lies outside the receiver.
func (GeogExpr[E]) DWithin ¶
DWithin reports whether the two geographies are within metres of one another.
Metres, on the spheroid, whatever the latitude — which is the whole reason to store a geography. The plane form of this takes the coordinate system's units and is a different question; see GeomExpr.DWithin.
func (GeogExpr[E]) DeclaredSRID ¶
DeclaredSRID reports the coordinate system the expression's result is in, which for a geography is almost always 4326.
func (GeogExpr[E]) Distance ¶
Distance is the shortest distance between the two geographies, in metres.
func (GeogExpr[E]) DistanceNull ¶
DistanceNull is GeogExpr.Distance where either side can be NULL.
func (GeogExpr[E]) Intersects ¶
Intersects reports whether the two geographies share any point.
func (GeogExpr[E]) KNNDistance ¶
KNNDistance builds the <-> operator over geographies, which orders by distance on the sphere through a spatial index.
func (GeogExpr[E]) LengthNull ¶
LengthNull is GeogExpr.Length over a geography that can be NULL.
func (GeogExpr[E]) Perimeter ¶
Perimeter is the length of a geography polygon's boundary, in metres.
type Geography ¶
type Geography struct {
// contains filtered or unexported fields
}
Geography is a geometry on the spheroid.
It holds the same coordinates a Geometry does and is a different Go type, because PostgreSQL treats it as a different type and the difference is not cosmetic:
ST_Distance over geometry(4326) degrees, and not a distance anyone wants ST_Distance over geography(4326) metres along the spheroid
Both compile, both return a float8, and only one of them answers "how far apart are these two places". Nothing in this package converts between them on your behalf; Geometry.AsGeography and Geography.AsGeometry are how the conversion is written down, and they are the only way it happens.
The coordinates are longitude then latitude, in that order, because that is the order PostGIS reads them in: X is longitude. A pair written the other way round compiles, stores and returns wrong answers.
func GeographyPoint ¶
GeographyPoint returns a point on the spheroid at the given longitude and latitude, in SRID 4326.
The argument order is the one PostGIS uses and the opposite of how a place is usually spoken: longitude first.
func NewGeography ¶
NewGeography is Geometry.AsGeography for a geometry built inline, which is the common case.
func (Geography) AppendEWKB ¶
AppendEWKB appends the value's EWKB encoding to dst.
func (Geography) AsGeometry ¶
AsGeometry reinterprets the geography's positions as plane coordinates.
The numbers are unchanged; what changes is that distances and areas over the result are in the SRID's units rather than in metres.
func (Geography) EWKB ¶
EWKB returns the value's EWKB encoding, which is the same encoding a geometry with these coordinates has — on the wire the two types are identical, and only the column tells them apart.
func (Geography) Equal ¶
Equal reports structural equality, with the same meaning it has on Geometry.Equal: same shape, same coordinates, same SRID, and not the topological question ST_Equals answers.
func (Geography) Geometries ¶
Geometries returns the members of a collection or multi value.
func (Geography) IsEmpty ¶
IsEmpty reports whether this is one of PostGIS's empty values, which is not the same as being NULL.
type GeomCol ¶
GeomCol is a NOT NULL geometry column of entity E.
func NewGeomCol ¶
NewGeomCol returns a geometry column descriptor. Generated code calls it.
srid, kind and dim come from the column's declared type — geometry(Point,4326) gives all three, plain geometry gives none — and are what the build-time checks read. Passing UnknownSRID and a zero Kind means "the column does not say", which switches the corresponding check off rather than assuming a default.
func (GeomCol[E]) Expr ¶
Expr lifts the column into a spatial expression, which is what the operations in this package compose over.
Every spatial method is on GeomExpr rather than repeated on each of the four descriptors, and this is the one step between them. It is a method rather than something implicit because the descriptors differ in exactly one way that matters — whether the column can be NULL — and this is where that fact is recorded.
func (GeomCol[E]) Kind ¶
Kind reports the shape the column's type constrains it to, or zero when its type accepts any.
func (GeomCol[E]) SRID ¶
SRID reports the coordinate system the column is declared in, or UnknownSRID when its type does not constrain one.
type GeomExpr ¶
type GeomExpr[E any] struct { // contains filtered or unexported fields }
GeomExpr is a geometry-valued expression over entity E.
It is what every geometry column, constructor and transformation produces, so operations chain: buffer a column, take the centroid of the result, ask whether that intersects something. The entity tag rides along, which is what keeps a predicate built from one table's columns out of another table's query.
It carries what it knows about itself. The SRID and the shape come from the column's declared type or from the constructor that produced it, and they are what the build-time checks read; both are permitted to be unknown, and an unknown one is not checked rather than assumed.
func Compose ¶
Compose drops the entity tag from a spatial expression that already is one, which is what a chain of transformations produces.
func FromExpr ¶
FromExpr lifts a geometry-valued expression this package did not build.
A derived table or a CTE that projects a geometry hands back an ordinary orm.Expression, because the ORM's own machinery has no reason to know about PostGIS. This is how such a column re-enters the spatial layer: the caller states what the projected geometry is, because the projection did not carry it — a CTE column's type is whatever the CTE selected, and no part of the query records that it happened to be a point in 4326.
That makes it a trust boundary of the same kind orm.RawValue is: nothing checks the claim, and a wrong one makes the build-time SRID check wrong rather than the query wrong. Pass the zero TypeMod to claim nothing, which switches those checks off and leaves the server as the only authority.
loc := orm.Named("location", orm.Of(Places.Location))
near := orm.CTE("near", orm.Rows(loc).From(Places.Source()))
postgis.FromExpr(orm.Ref(near, loc), Places.Location.TypeMod())
func FromExprNull ¶
FromExprNull is FromExpr for a projected geometry that can be NULL.
func GeomFromEWKB ¶
GeomFromEWKB parses PostGIS's extended WKB.
It exists for bytes that arrived from somewhere else already encoded — a cache, a message queue, another system's export. A geometry this program holds needs none of it: Value sends the same encoding through the codec with no function call in the way.
func GeomFromGeoJSON ¶
GeomFromGeoJSON parses a GeoJSON geometry object.
The document is a bind parameter. GeoJSON is defined in WGS 84 and PostGIS tags the result 4326, which is what the expression records.
func GeomFromGeoJSONExpr ¶
func GeomFromGeoJSONExpr[E any](doc orm.Selectable[E, string]) GeomExpr[E]
GeomFromGeoJSONExpr is GeomFromGeoJSON where the document comes from a column — a jsonb column rendered to text, or a text column holding one.
func GeomFromText ¶
GeomFromText parses WKT into a geometry, in the given coordinate system.
The SRID is required rather than optional, for the same reason MakeEnvelope's is: PostGIS's one-argument form produces SRID 0, and a geometry in SRID 0 silently fails to relate to anything in a table that has one. Pass UnknownSRID deliberately when that really is what is meant.
Malformed WKT is PostGIS's error, unchanged. This package does not parse WKT and so has no second opinion about what is malformed.
func GeomFromTextExpr ¶
GeomFromTextExpr is GeomFromText where the text comes from a column.
func MakeEnvelope ¶
MakeEnvelope builds the rectangle between two corners, which is what a map viewport is.
The SRID is required rather than optional. PostGIS's own two-argument form defaults to 0, and a viewport in SRID 0 intersects nothing in a 4326 table — a query that silently returns no rows rather than failing.
func MakePoint ¶
func MakePoint[E any](x, y orm.Selectable[E, float64]) GeomExpr[E]
MakePoint builds ST_MakePoint from two expressions.
The result has no SRID, because ST_MakePoint does not assign one: PostGIS returns a geometry in SRID 0, and a package that quietly made it 4326 would put every constructed point somewhere on Earth by accident. Wrap it in GeomExpr.SetSRID to say which coordinate system the numbers are in.
The ordinates are ordinary value expressions, so a point can be built from two columns — which is what a table of latitudes and longitudes needs, and the reason this exists alongside the Go-side NewPoint.
func MakePointM ¶
func MakePointM[E any](x, y, m orm.Selectable[E, float64]) GeomExpr[E]
MakePointM builds ST_MakePointM, which takes a measure rather than an elevation.
It is a different function in PostGIS rather than a fourth argument, because ST_MakePoint with three arguments means Z. Getting that wrong stores a measure where an elevation belongs and nothing complains.
func MakePointZ ¶
func MakePointZ[E any](x, y, z orm.Selectable[E, float64]) GeomExpr[E]
MakePointZ builds ST_MakePoint with an elevation.
func Of ¶
Of lifts a column of any entity into a composed spatial expression.
postgis.Intersects(postgis.Of(Parks.Area), postgis.Of(Roads.Path))
The entity tag is dropped and nothing else is: the SRID, the shape and the nullability travel through, so a composed query gets the same checks an entity query does.
func Value ¶
Value lifts a geometry into an expression, as a bind parameter.
The coordinates are never text. They cross as EWKB in the statement's parameter list, which is the same path every other value in this package takes and the reason there is no way to interpolate a coordinate into SQL.
The cast is not decoration: PostGIS overloads almost every function on geometry and geography, and an uncast parameter leaves PostgreSQL resolving the overload with nothing to go on — it picks the deprecated text form and fails on bytes that were never text.
func (GeomExpr[E]) Area ¶
Area is the geometry's area in the units of its coordinate system.
Over geometry(4326) that is square degrees, which is not an area anybody wants: a square degree is not a fixed size. Cast to geography, or use a projected coordinate system, when square metres are meant.
func (GeomExpr[E]) AreaNull ¶
AreaNull is GeomExpr.Area over a geometry that can be NULL.
func (GeomExpr[E]) AsBinaryNull ¶
AsBinaryNull is GeomExpr.AsBinary over a geometry that can be NULL.
func (GeomExpr[E]) AsEWKB ¶
AsEWKB renders the geometry as PostGIS's extended WKB, which carries the SRID.
It is the same encoding Geometry.EWKB produces and the codec sends, so a query needs it only when the bytes themselves are the result — a cache key, a checksum, a payload for something else that speaks EWKB.
func (GeomExpr[E]) AsEWKBNull ¶
AsEWKBNull is GeomExpr.AsEWKB over a geometry that can be NULL.
func (GeomExpr[E]) AsEWKT ¶
AsEWKT renders the geometry as PostGIS's extended WKT, which prefixes the SRID: SRID=4326;POINT(1 2).
func (GeomExpr[E]) AsEWKTNull ¶
AsEWKTNull is GeomExpr.AsEWKT over a geometry that can be NULL.
func (GeomExpr[E]) AsGeoJSON ¶
AsGeoJSON renders the geometry as a GeoJSON geometry object.
It reads back as a string rather than as a parsed document, because that is what PostGIS returns: ST_AsGeoJSON's result type is text, not json and not jsonb. Claiming otherwise would put a jsonb codec in front of bytes the server never marked as one.
GeoJSON is defined in WGS 84, so a geometry in another coordinate system should be transformed before rendering — PostGIS does not do it and neither does this.
func (GeomExpr[E]) AsGeoJSONNull ¶
AsGeoJSONNull is GeomExpr.AsGeoJSON over a geometry that can be NULL.
func (GeomExpr[E]) AsGeography ¶
AsGeography casts a geometry expression to geography, which is how a query asks for metres from a column stored in the plane.
It is written out rather than inferred, exactly as Geometry.AsGeography is: the cast changes what the numbers mean, and PostGIS's own implicit cast to 4326 is a guess this package does not make. The expression must already state its coordinate system.
func (GeomExpr[E]) AsText ¶
AsText renders the geometry as WKT, which is the OGC's text form and carries no SRID.
Use GeomExpr.AsEWKT when the coordinate system has to survive the rendering, which for anything leaving the program it usually does.
func (GeomExpr[E]) AsTextNull ¶
AsTextNull is GeomExpr.AsText over a geometry that can be NULL.
func (GeomExpr[E]) Azimuth ¶
Azimuth is the bearing from one point to another, in radians clockwise from north, and NULL when the two points are in the same place.
func (GeomExpr[E]) BBoxContains ¶
BBoxContains builds the ~ operator: the receiver's bounding box contains the other's.
func (GeomExpr[E]) BBoxDistance ¶
BBoxDistance builds the <#> operator: the distance between the two geometries' bounding boxes.
func (GeomExpr[E]) BBoxIntersects ¶
BBoxIntersects builds the && operator: the two bounding boxes overlap.
It is the cheap test the exact predicates run first, exposed on its own because sometimes the box is the question — a viewport, a tile, a coarse filter before something expensive. It is not a substitute for [Intersects]: two geometries whose boxes overlap need not touch at all.
func (GeomExpr[E]) BBoxSame ¶
BBoxSame builds the ~= operator: the two bounding boxes are identical.
func (GeomExpr[E]) BBoxWithin ¶
BBoxWithin builds the @ operator: the receiver's bounding box is contained by the other's.
func (GeomExpr[E]) Boundary ¶
Boundary is the geometry's boundary: the ring of a polygon, the endpoints of a line.
func (GeomExpr[E]) Buffer ¶
Buffer grows the geometry by distance in every direction, in the units of its coordinate system.
The result's shape is deliberately unconstrained. A positive buffer of anything is a polygon or a multi-polygon, and a negative buffer of a polygon can collapse to an empty geometry — so the metadata claims nothing and the value reports what it is.
func (GeomExpr[E]) Centroid ¶
Centroid is the geometry's centre of mass, which PostGIS guarantees is a point — so the result metadata says Point, and that is one of the few places it can.
The centroid of an empty geometry is an empty point, and the centroid of a NULL is NULL. They are different answers and both come back.
func (GeomExpr[E]) CollectionExtract ¶
CollectionExtract pulls the members of one shape out of a collection, which is how the polygon part of an ST_Intersection result is isolated.
func (GeomExpr[E]) Contains ¶
Contains reports whether the receiver contains the other geometry entirely, with no point of the other outside it and at least one point inside.
A geometry does not contain a point that lies exactly on its boundary. That is ST_Covers, and the difference is the boundary — which is where the points that matter usually are.
func (GeomExpr[E]) ContainsProperly ¶
ContainsProperly reports whether the other geometry lies in the receiver's interior, touching no part of its boundary.
func (GeomExpr[E]) ConvexHull ¶
ConvexHull is the smallest convex geometry containing this one.
Like GeomExpr.Envelope it can be a point, a line or a polygon depending on what it was given, so it claims no shape.
func (GeomExpr[E]) CoordDim ¶
CoordDim is how many ordinates each position carries: two, three or four.
It reads back as int16 because PostGIS returns smallint for this one and integer for every other counting function beside it. Claiming int32 would compile, scan and be wrong about the type the server sent — which is the reason every one of these is checked against pg_typeof rather than guessed from the name.
func (GeomExpr[E]) CoveredBy ¶
CoveredBy reports whether no point of the receiver lies outside the other geometry. It is Covers with the operands the other way round.
func (GeomExpr[E]) Covers ¶
Covers reports whether no point of the other geometry lies outside the receiver.
This is the one that includes the boundary, and it is usually what somebody means by "contains": a point on the edge of a district is in the district.
func (GeomExpr[E]) Crosses ¶
Crosses reports whether the two geometries pass through one another: a line crossing a polygon, or two lines meeting at a point.
func (GeomExpr[E]) DFullyWithin ¶
DFullyWithin reports whether every part of each geometry is within distance of every part of the other, which is a question about the farthest points rather than the nearest.
func (GeomExpr[E]) DWithin ¶
DWithin reports whether the two geometries are within distance of one another, measured in the units of their coordinate system.
The units are the trap. Over geometry(4326) the distance is in degrees, and a degree is about 111 km at the equator and much less near the poles — so a query written with 1000 for "a kilometre" selects most of a continent. Use a geography, or a projected coordinate system, when the answer should be in metres; see GeogExpr.DWithin.
It is the predicate a GiST index accelerates best, because PostGIS expands the bounding box by the distance and searches that.
func (GeomExpr[E]) DeclaredDim ¶
DeclaredDim reports the dimensionality the expression is known to produce.
func (GeomExpr[E]) DeclaredKind ¶
DeclaredKind reports the shape the expression is known to produce, or zero when it may produce any.
func (GeomExpr[E]) DeclaredSRID ¶
DeclaredSRID reports the coordinate system the expression's result is in, or UnknownSRID when the expression does not say.
It is what the column's declared type or the constructor said, known while the query is being built — where GeomExpr.SRID asks the server what the stored geometry is actually labelled with, and is an expression rather than a number. A plain geometry column has no declared SRID and holds geometries that each have one.
func (GeomExpr[E]) Difference ¶
Difference is the part of the receiver that is not in the other geometry.
func (GeomExpr[E]) Dimension ¶
Dimension is the geometry's topological dimension: zero for a point, one for a line, two for a polygon.
func (GeomExpr[E]) Disjoint ¶
Disjoint reports whether the two geometries share no point.
PostGIS does not index this one: there is no bounding box that proves two geometries do not touch, so it is a full scan. Prefer Not(Intersects) when the query has an index to use.
func (GeomExpr[E]) Distance ¶
Distance is the shortest distance between the two geometries, in the units of their coordinate system.
It is zero when they touch. Over geometry(4326) the answer is in degrees; see GeogExpr.Distance for metres.
func (GeomExpr[E]) DistanceNull ¶
DistanceNull is GeomExpr.Distance where either geometry can be NULL, and is nullable because PostgreSQL's answer then is NULL rather than zero — a distinction that matters, because zero means "they touch".
func (GeomExpr[E]) Envelope ¶
Envelope is the geometry's bounding box as a geometry.
It is not always a polygon, which is why the result claims no shape: the envelope of a point is a point, the envelope of a horizontal line is a line, and only the general case is a rectangle. A package that typed this Polygon would be wrong about two of the three.
func (GeomExpr[E]) EqualsGeom ¶
EqualsGeom reports whether the two geometries occupy the same space.
This is topological equality, which is not the same as being made of the same vertices: a line drawn backwards equals itself, and a polygon with a repeated point equals the one without. It is the question a database should answer, and Geometry.Equal in Go deliberately answers the other one.
The name is not Equals because the embedded column descriptor already has Eq, which is PostgreSQL's = — an exact comparison of the stored representation, and a different question again.
func (GeomExpr[E]) Force2D ¶
Force2D drops the Z and M ordinates.
It is spelled out because it loses data. A column typed geometry(PointZ,4326) does not accept the result, and this package will not do it implicitly to make an assignment typecheck.
func (GeomExpr[E]) GeometryType ¶
GeometryType is the shape's name as PostGIS spells it: ST_Point, ST_Polygon, and so on, with the ST_ prefix that GeometryType does not have.
func (GeomExpr[E]) Intersection ¶
Intersection is the part the two geometries have in common.
The shape depends entirely on how they meet — two polygons crossing give a polygon, two polygons touching along an edge give a line, two touching at a corner give a point, and two that miss give an empty geometry — so the result claims none.
func (GeomExpr[E]) Intersects ¶
Intersects reports whether the two geometries share any point at all.
It is the negation of ST_Disjoint and the predicate most spatial queries want. An empty geometry intersects nothing, including itself.
func (GeomExpr[E]) IsEmptyGeom ¶
IsEmptyGeom reports whether the geometry has no points.
It is not a NULL test. A NULL column has no geometry; an empty geometry is a geometry that covers nothing, and the two travel different paths through every query. Ask IsNull for the other question — the nullable descriptors have it, and the non-nullable ones deliberately do not.
func (GeomExpr[E]) IsSimple ¶
IsSimple reports whether the geometry has no anomalous points: a line that does not cross itself, a multi-point with no repeats.
func (GeomExpr[E]) IsValid ¶
IsValid reports whether the geometry is one PostGIS considers well formed: a polygon whose rings close and do not cross themselves, and so on.
An invalid geometry is stored happily and gives wrong answers to almost every predicate, so this is worth asking about data that came from somewhere else.
func (GeomExpr[E]) IsValidReason ¶
IsValidReason explains why a geometry is invalid, in PostGIS's words.
It returns "Valid Geometry" for a valid one rather than NULL, which is why the result is a plain string.
func (GeomExpr[E]) IsValidReasonNull ¶
IsValidReasonNull is GeomExpr.IsValidReason over a geometry that can be NULL.
func (GeomExpr[E]) KNNDistance ¶
KNNDistance builds the <-> operator, which is what an ORDER BY uses to find the nearest rows through a spatial index.
This is the one to reach for when the question is "the ten closest", because PostgreSQL can walk a GiST index in distance order and stop after ten. An ORDER BY ST_Distance cannot: it has to measure every row first.
q.OrderBy(places.Location.Expr().KNNDistance(here).Asc()).Limit(10)
The number it returns is a distance between the geometries' centroids in recent PostGIS and between their bounding boxes in older ones. Order by it; do not report it as the distance.
func (GeomExpr[E]) Length ¶
Length is the geometry's length in the units of its coordinate system. It is zero for anything that is not a line.
func (GeomExpr[E]) LengthNull ¶
LengthNull is GeomExpr.Length over a geometry that can be NULL.
func (GeomExpr[E]) M ¶
M is the point's measure, with the same cases GeomExpr.Z has: NULL for a point carrying no measure, an error for something that is not a point.
func (GeomExpr[E]) MakeValid ¶
MakeValid repairs an invalid geometry.
The shape can change — a self-intersecting polygon becomes a multi-polygon, and a degenerate one can become a line — so the result claims none. Nothing calls this on your behalf: an invalid geometry is data somebody should look at, and quietly repairing it on the way through a query would hide that.
func (GeomExpr[E]) MaxDistance ¶
MaxDistance is the greatest distance between any point of one geometry and any point of the other.
func (GeomExpr[E]) Multi ¶
Multi wraps a geometry in its multi form, which is what a column typed geometry(MultiPolygon,4326) requires of a polygon.
func (GeomExpr[E]) NumGeometries ¶
NumGeometries is how many members a collection or multi geometry has, and one for a simple geometry.
func (GeomExpr[E]) NumPoints ¶
NumPoints is how many positions the geometry holds, across every ring and every member.
func (GeomExpr[E]) Overlaps ¶
Overlaps reports whether the two geometries share some but not all of their points, and have the same dimension.
Two polygons that partly cover one another overlap. A polygon and a point do not, whatever their positions, because their dimensions differ.
func (GeomExpr[E]) Perimeter ¶
Perimeter is the length of a polygon's boundary, and zero for anything else.
func (GeomExpr[E]) PerimeterNull ¶
PerimeterNull is GeomExpr.Perimeter over a geometry that can be NULL.
func (GeomExpr[E]) PointOnSurface ¶
PointOnSurface is a point guaranteed to lie on the geometry, which the centroid of a crescent is not.
func (GeomExpr[E]) Relate ¶
Relate builds ST_Relate against a DE-9IM intersection matrix pattern.
The pattern is nine characters describing how the interiors, boundaries and exteriors of the two geometries meet — the general form every named predicate above is a special case of. It is validated here rather than sent as written, because a pattern is a value from the caller and it reaches the server as a bind parameter either way; the check is so a typo fails with a message about the pattern instead of a PostGIS error about a matrix.
func (GeomExpr[E]) SRID ¶
SRID is the coordinate system the stored geometry is labelled with.
It is the server's answer rather than the column's declaration, which is why it exists: a plain geometry column can hold geometries in several coordinate systems, and this is how a query finds out which.
func (GeomExpr[E]) SetSRID ¶
SetSRID labels the geometry with a coordinate system.
It changes the metadata and not one coordinate. A point at (1, 2) with SRID set to 3857 is still at (1, 2); it is now claimed to be 1 metre east and 2 metres north of the web-Mercator origin rather than 1 degree east and 2 degrees north of Greenwich, which is a different place on Earth for the same pair of numbers.
Use it when the coordinates are already right and the label is missing — after ST_MakePoint, or over a column somebody loaded without one. Use GeomExpr.Transform when the coordinates need to move.
func (GeomExpr[E]) Simplify ¶
Simplify removes vertices using Douglas-Peucker, keeping the result within tolerance of the original.
It can break topology: two polygons that shared a boundary may not afterwards, and a polygon can simplify into something invalid. That is the algorithm rather than an implementation detail, and GeomExpr.SimplifyPreserveTopology is the slower function that does not do it.
func (GeomExpr[E]) SimplifyPreserveTopology ¶
SimplifyPreserveTopology removes vertices while keeping the result valid and keeping components that would otherwise vanish.
It is not GeomExpr.Simplify with a flag: it is a different algorithm with a different cost and a different result, and the two are offered separately because choosing between them is a real decision.
func (GeomExpr[E]) SymDifference ¶
SymDifference is the part of either geometry that is not in both.
func (GeomExpr[E]) Touches ¶
Touches reports whether the two geometries meet at their boundaries and share no interior point.
func (GeomExpr[E]) Transform ¶
Transform reprojects the geometry into another coordinate system.
The coordinates move. PostGIS does the projection using the definitions in spatial_ref_sys, which is why nothing here computes one: a projection is a large body of geodesy that belongs in PROJ and not in an ORM.
It needs a source coordinate system to project from, so an expression whose SRID is unknown is refused rather than guessed at.
func (GeomExpr[E]) Union ¶
Union is the two geometries together, as one.
This is the two-argument ST_Union, which is a different function from the aggregate of the same name: this combines two values in a row, and UnionAgg combines every row of a group.
func (GeomExpr[E]) ValueNull ¶
ValueNull reads the expression's result as a geometry that may be NULL.
func (GeomExpr[E]) Within ¶
Within reports whether the receiver lies entirely inside the other geometry. It is Contains with the operands the other way round.
func (GeomExpr[E]) X ¶
X is the point's first ordinate.
It is NULL when the geometry is NULL, and an error when the geometry is not a point.
func (GeomExpr[E]) Y ¶
Y is the point's second ordinate, with the same two cases GeomExpr.X has.
type Geometry ¶
type Geometry struct {
// contains filtered or unexported fields
}
Geometry is any shape, with its dimensionality and spatial reference.
It is one Go type rather than seven because a shape is data rather than a type in PostGIS too: a geometry column declared without a modifier holds any of them, ST_Intersection returns whichever the answer is, and a Go type per shape would make those unrepresentable. What is typed here is the column and the expression; the value carries its own shape and reports it.
The coordinate storage is flat and the structure is carried beside it, which is what keeps a polygon with a thousand vertices one allocation rather than a thousand.
func DecodeEWKB ¶
DecodeEWKB reads a geometry from its EWKB encoding.
It accepts either byte order and both the SRID-bearing and plain forms, since what arrives depends on which function produced it: ST_AsBinary drops the SRID and ST_AsEWKB keeps it. A geometry decoded from plain WKB has UnknownSRID, which is the truth about it rather than a default.
func EmptyPoint ¶
EmptyPoint returns POINT EMPTY, which is a point with no position.
func NewCollection ¶
NewCollection returns a geometry collection.
The members keep their own shapes. Their spatial references have to agree with the collection's, because a collection whose members disagree is not a value PostGIS can store.
func NewLineString ¶
NewLineString returns a line through the given positions.
func NewMultiLineString ¶
NewMultiLineString returns several lines as one geometry.
func NewMultiPoint ¶
NewMultiPoint returns several points as one geometry.
func NewMultiPolygon ¶
NewMultiPolygon returns several polygons as one geometry, each given as its list of rings.
func NewPointZM ¶
NewPointZM returns a point with both an elevation and a measure.
func NewPolygon ¶
NewPolygon returns a polygon from its rings, the first being the exterior one.
PostGIS decides whether the rings are closed and correctly nested; nothing here closes a ring for you, because a ring that needed closing is a ring somebody got wrong and silently fixing it hides that.
func (Geometry) AppendEWKB ¶
AppendEWKB appends the geometry's EWKB encoding to dst and returns it.
The SRID is written whenever the geometry has one, which is what makes the round trip lossless: a geometry that went in as 4326 comes back as 4326 rather than as an unlabelled set of numbers.
func (Geometry) AsGeography ¶
AsGeography reinterprets the geometry's coordinates as positions on the spheroid.
This is a cast, exactly as `geom::geography` is: the numbers do not change, only what they are taken to mean. It requires an SRID, because a geography with no spatial reference is a set of numbers with no surface to be on — and PostGIS's own cast would silently supply 4326, which is a guess this package will not make for you.
func (Geometry) Coords ¶
Coords returns every position of the geometry, in order.
The slice is freshly built, so a caller may keep or modify it without reaching back into the geometry — which matters because a geometry inside a built query has to stay the geometry that query was built from.
func (Geometry) Equal ¶
Equal reports whether two geometries hold the same value.
This is structural equality — same shape, same dimensionality, same SRID, same coordinates in the same order — and it is deliberately not ST_Equals. PostGIS's ST_Equals is a topological question the server answers, and two geometries that trace the same shape with different vertex order are equal to it and not to this. Ask the server when the topological answer is what is meant.
func (Geometry) Geometries ¶
Geometries returns the members of a collection or multi geometry.
The result is a copy for the same reason Geometry.Coords is.
func (Geometry) IsEmpty ¶
IsEmpty reports whether the geometry is one of PostGIS's empty values.
An empty geometry is not NULL. POINT EMPTY is a point that happens to have no position, and a column holding one holds a value; a NULL column holds none. The two are different in SQL and are different here.
func (Geometry) NumPoints ¶
NumPoints reports how many positions the geometry holds, across every ring and every member.
func (Geometry) SRID ¶
SRID reports the spatial reference the coordinates are in, which is UnknownSRID when the geometry has none.
func (Geometry) String ¶
String renders the geometry for a person, in the shape of PostGIS's own EWKT.
It is a diagnostic rather than a serialisation: use ST_AsEWKT when the text has to be PostGIS's.
func (Geometry) WithSRID ¶
WithSRID returns the geometry labelled with a spatial reference.
This is ST_SetSRID's semantics in Go: it changes which coordinate system the numbers are said to be in and does not touch the numbers. Use it when the coordinates are already right and only the label is missing.
type Kind ¶
type Kind uint8
Kind is a geometry's shape.
const ( KindPoint Kind = iota + 1 KindLineString KindPolygon KindMultiPoint KindMultiLineString KindMultiPolygon KindCollection )
The shapes this package models. They are PostGIS's own type codes in the same order, which is what makes the codec a lookup rather than a switch.
type NotInstalledError ¶
type NotInstalledError struct{}
NotInstalledError reports a database with no PostGIS extension.
func (*NotInstalledError) Error ¶
func (*NotInstalledError) Error() string
Error explains that the database has no PostGIS, and how to add it.
type NullGeogCol ¶
type NullGeogCol[E any] struct { orm.NullCol[E, Geography] // contains filtered or unexported fields }
NullGeogCol is a nullable geography column of entity E.
func NewNullGeogCol ¶
func NewNullGeogCol[E any](src *orm.Source, name string, srid int32, kind Kind, dim Dim) NullGeogCol[E]
NewNullGeogCol returns a nullable geography column descriptor.
func (NullGeogCol[E]) Area ¶
func (c NullGeogCol[E]) Area() orm.Value[E, *float64]
Area is the column's area in square metres, and can be NULL because the column can.
func (NullGeogCol[E]) Dim ¶
func (c NullGeogCol[E]) Dim() Dim
Dim reports the dimensionality the column's type constrains it to.
func (NullGeogCol[E]) Expr ¶
func (c NullGeogCol[E]) Expr() GeogExpr[E]
Expr lifts the column into a spatial expression on the spheroid, which is nullable because the column is.
func (NullGeogCol[E]) Kind ¶
func (c NullGeogCol[E]) Kind() Kind
Kind reports the shape the column's type constrains it to, or zero when its type accepts any.
func (NullGeogCol[E]) Length ¶
func (c NullGeogCol[E]) Length() orm.Value[E, *float64]
Length is the column's length in metres, and can be NULL because the column can.
func (NullGeogCol[E]) SRID ¶
func (c NullGeogCol[E]) SRID() int32
SRID reports the coordinate system the column is declared in, or UnknownSRID when its type does not constrain one.
func (NullGeogCol[E]) TypeMod ¶
func (c NullGeogCol[E]) TypeMod() TypeMod
TypeMod returns what the column's declared type says it holds, which is what FromExpr needs when that column is projected through a derived table.
type NullGeomCol ¶
type NullGeomCol[E any] struct { orm.NullCol[E, Geometry] // contains filtered or unexported fields }
NullGeomCol is a nullable geometry column of entity E.
It selects as *Geometry, because NULL and an empty geometry are different answers and only a pointer can tell them apart.
func NewNullGeomCol ¶
func NewNullGeomCol[E any](src *orm.Source, name string, srid int32, kind Kind, dim Dim) NullGeomCol[E]
NewNullGeomCol returns a nullable geometry column descriptor.
func (NullGeomCol[E]) Area ¶
func (c NullGeomCol[E]) Area() orm.Value[E, *float64]
Area is the column's area, and can be NULL because the column can.
func (NullGeomCol[E]) Dim ¶
func (c NullGeomCol[E]) Dim() Dim
Dim reports the dimensionality the column's type constrains it to.
func (NullGeomCol[E]) Expr ¶
func (c NullGeomCol[E]) Expr() GeomExpr[E]
Expr lifts the column into a spatial expression, which is nullable because the column is.
func (NullGeomCol[E]) Kind ¶
func (c NullGeomCol[E]) Kind() Kind
Kind reports the shape the column's type constrains it to, or zero when its type accepts any.
func (NullGeomCol[E]) Length ¶
func (c NullGeomCol[E]) Length() orm.Value[E, *float64]
Length is the column's length, and can be NULL because the column can.
func (NullGeomCol[E]) SRID ¶
func (c NullGeomCol[E]) SRID() int32
SRID reports the coordinate system the column is declared in, or UnknownSRID when its type does not constrain one.
func (NullGeomCol[E]) TypeMod ¶
func (c NullGeomCol[E]) TypeMod() TypeMod
TypeMod returns what the column's declared type says it holds, which is what FromExpr needs when that column is projected through a derived table.
type TypeMod ¶
type TypeMod struct {
// Family is whether the column is geometry or geography, which is the one
// part of a modifier that is never optional: the two have different
// operators and different answers for the same question.
Family Family
// Kind is the shape the column accepts, or zero for any.
Kind Kind
// Dim is the dimensionality the column accepts. It is [XY] both when the
// column requires two dimensions and when it constrains nothing, which
// HasDim separates.
Dim Dim
// SRID is the coordinate system the column requires, or [UnknownSRID] for
// none.
SRID int32
// contains filtered or unexported fields
}
TypeMod is a spatial column's declared type, taken apart.
Zero values mean "the declaration does not constrain this", which is what a bare geometry says about all three. They do not mean a default: a column with no SRID constraint holds geometries whose SRIDs are their own business, and nothing here fills in 4326.
func ParseTypeMod ¶
ParseTypeMod reads a PostgreSQL spatial type declaration.
It accepts what PostgreSQL renders and what a person writes, which differ only in case and spacing: geometry(Point,4326), GEOMETRY(POINTZ, 4326) and geometry are all the same declarations they look like. Anything that is not a spatial type parses to the zero TypeMod with no error, so a caller can ask about every column without deciding first.
It is strict about the parts it does understand. A shape PostGIS does not have, an SRID that is not a number, a modifier with three parts — each is an error naming what was wrong, because a declaration nobody can read is a column nobody can generate for.
func (TypeMod) Accepts ¶
Accepts reports whether a value can be stored in a column of this declaration, and says why not when it cannot.
This is the check PostGIS performs on INSERT, done early enough to name the field. It is deliberately the same rule rather than a stricter one: a column with no modifier accepts anything, and a constrained one accepts exactly what its modifier says.
func (TypeMod) Constrained ¶
Constrained reports whether the declaration constrains the shape, dimensionality or coordinate system at all.
It is one answer rather than three because a PostGIS modifier constrains all three or none: geometry(Point,4326) requires two dimensions as much as it requires a point, and a bare geometry requires nothing.
func (TypeMod) GoType ¶
GoType names the Go type a column of this declaration reads into.
It is the generator's answer to "what does this field have to be", and it is two answers rather than seven: the shape lives in the value and in the descriptor's metadata, not in the Go type. A column typed geometry(Polygon,4326) reads into a Geometry that happens to be a polygon, because that is what PostGIS hands back and because ST_Intersection of two polygons is not always one.