From 08ef713a5d7332cb6fc2c60350f01fa3e7a67e82 Mon Sep 17 00:00:00 2001 From: Oliver Tan Date: Sat, 22 Aug 2020 10:32:17 -0700 Subject: [PATCH 1/2] geo: remove pointer usage for Geometry/Geography This should improve our heap profiles by making tree.DGeometry/Geography only implant a geo.Geometry/Geography object. Release justification: low risk, high reward changes to existing functionality Release note: None --- pkg/cmd/geoviz/geoviz.go | 2 +- pkg/geo/geo.go | 172 +++++++++--------- pkg/geo/geo_test.go | 4 +- pkg/geo/geogen/geogen.go | 8 +- pkg/geo/geogfn/azimuth.go | 4 +- pkg/geo/geogfn/covers.go | 10 +- pkg/geo/geogfn/distance.go | 4 +- pkg/geo/geogfn/dwithin.go | 6 +- pkg/geo/geogfn/intersects.go | 4 +- pkg/geo/geogfn/segmentize.go | 12 +- pkg/geo/geogfn/topology_operations.go | 14 +- pkg/geo/geogfn/unary_operators.go | 20 +- pkg/geo/geogfn/unary_operators_test.go | 12 +- pkg/geo/geoindex/geoindex.go | 26 +-- pkg/geo/geoindex/s2_geography_index.go | 14 +- pkg/geo/geoindex/s2_geography_index_test.go | 2 +- pkg/geo/geoindex/s2_geometry_index.go | 19 +- pkg/geo/geoindex/s2_geometry_index_test.go | 6 +- pkg/geo/geomfn/azimuth.go | 4 +- pkg/geo/geomfn/binary_predicates.go | 44 ++--- pkg/geo/geomfn/binary_predicates_test.go | 44 ++--- pkg/geo/geomfn/buffer.go | 4 +- pkg/geo/geomfn/collections.go | 58 +++--- pkg/geo/geomfn/de9im.go | 8 +- pkg/geo/geomfn/de9im_test.go | 4 +- pkg/geo/geomfn/distance.go | 44 ++--- pkg/geo/geomfn/distance_test.go | 3 +- pkg/geo/geomfn/envelope.go | 4 +- pkg/geo/geomfn/flip_coordinates.go | 8 +- pkg/geo/geomfn/flip_coordinates_test.go | 6 +- pkg/geo/geomfn/force.go | 8 +- pkg/geo/geomfn/linear_reference.go | 18 +- pkg/geo/geomfn/linestring.go | 26 +-- pkg/geo/geomfn/linestring_test.go | 16 +- pkg/geo/geomfn/make_geometry.go | 16 +- pkg/geo/geomfn/make_geometry_test.go | 12 +- pkg/geo/geomfn/reverse.go | 8 +- pkg/geo/geomfn/reverse_test.go | 10 +- pkg/geo/geomfn/scale.go | 28 +-- pkg/geo/geomfn/scale_test.go | 24 +-- pkg/geo/geomfn/segmentize.go | 10 +- pkg/geo/geomfn/topology_operations.go | 36 ++-- pkg/geo/geomfn/topology_operations_test.go | 19 +- pkg/geo/geomfn/translate.go | 8 +- pkg/geo/geomfn/translate_test.go | 8 +- pkg/geo/geomfn/unary_operators.go | 8 +- pkg/geo/geomfn/unary_predicates.go | 10 +- pkg/geo/geomfn/validity_check.go | 14 +- pkg/geo/geotransform/geotransform.go | 10 +- pkg/geo/parse.go | 8 +- pkg/geo/parse_test.go | 48 ++--- .../catalog/colinfo/column_type_properties.go | 4 +- pkg/sql/rowenc/column_type_encoding.go | 12 +- pkg/sql/sem/builtins/aggregate_builtins.go | 4 +- pkg/sql/sem/builtins/geo_builtins.go | 58 +++--- pkg/sql/sem/tree/casts.go | 10 +- pkg/sql/sem/tree/datum.go | 8 +- 57 files changed, 505 insertions(+), 506 deletions(-) diff --git a/pkg/cmd/geoviz/geoviz.go b/pkg/cmd/geoviz/geoviz.go index 2d6727bb6e98..1a3f004104c9 100644 --- a/pkg/cmd/geoviz/geoviz.go +++ b/pkg/cmd/geoviz/geoviz.go @@ -76,7 +76,7 @@ func s2PointToLatLng(fromPoint s2.Point) LatLng { } // AddGeography adds a given Geography to an image. -func (img *Image) AddGeography(g *geo.Geography, title string, color string) { +func (img *Image) AddGeography(g geo.Geography, title string, color string) { regions, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { panic(err) diff --git a/pkg/geo/geo.go b/pkg/geo/geo.go index d674ab7dee41..024c5daedcc6 100644 --- a/pkg/geo/geo.go +++ b/pkg/geo/geo.go @@ -99,54 +99,54 @@ type Geometry struct { spatialObject geopb.SpatialObject } -// NewGeometry returns a new Geometry. Assumes the input EWKB is validated and in little endian. -func NewGeometry(spatialObject geopb.SpatialObject) (*Geometry, error) { +// MakeGeometry returns a new Geometry. Assumes the input EWKB is validated and in little endian. +func MakeGeometry(spatialObject geopb.SpatialObject) (Geometry, error) { if spatialObject.SRID != 0 { if _, ok := geoprojbase.Projection(spatialObject.SRID); !ok { - return nil, errors.Newf("unknown SRID for Geometry: %d", spatialObject.SRID) + return Geometry{}, errors.Newf("unknown SRID for Geometry: %d", spatialObject.SRID) } } if spatialObject.Type != geopb.SpatialObjectType_GeometryType { - return nil, errors.Newf("expected geometry type, found %s", spatialObject.Type) + return Geometry{}, errors.Newf("expected geometry type, found %s", spatialObject.Type) } - return &Geometry{spatialObject: spatialObject}, nil + return Geometry{spatialObject: spatialObject}, nil } -// NewGeometryUnsafe creates a geometry object that assumes spatialObject is from the DB. +// MakeGeometryUnsafe creates a geometry object that assumes spatialObject is from the DB. // It assumes the spatialObject underneath is safe. -func NewGeometryUnsafe(spatialObject geopb.SpatialObject) *Geometry { - return &Geometry{spatialObject: spatialObject} +func MakeGeometryUnsafe(spatialObject geopb.SpatialObject) Geometry { + return Geometry{spatialObject: spatialObject} } -// NewGeometryFromPointCoords makes a point from x, y coordinates. -func NewGeometryFromPointCoords(x, y float64) (*Geometry, error) { +// MakeGeometryFromPointCoords makes a point from x, y coordinates. +func MakeGeometryFromPointCoords(x, y float64) (Geometry, error) { s, err := spatialObjectFromGeomT(geom.NewPointFlat(geom.XY, []float64{x, y}), geopb.SpatialObjectType_GeometryType) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(s) + return MakeGeometry(s) } -// NewGeometryFromGeomT creates a new Geometry object from a geom.T object. -func NewGeometryFromGeomT(g geom.T) (*Geometry, error) { +// MakeGeometryFromGeomT creates a new Geometry object from a geom.T object. +func MakeGeometryFromGeomT(g geom.T) (Geometry, error) { spatialObject, err := spatialObjectFromGeomT(g, geopb.SpatialObjectType_GeometryType) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(spatialObject) + return MakeGeometry(spatialObject) } // ParseGeometry parses a Geometry from a given text. -func ParseGeometry(str string) (*Geometry, error) { +func ParseGeometry(str string) (Geometry, error) { spatialObject, err := parseAmbiguousText(geopb.SpatialObjectType_GeometryType, str, geopb.DefaultGeometrySRID) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(spatialObject) + return MakeGeometry(spatialObject) } // MustParseGeometry behaves as ParseGeometry, but panics if there is an error. -func MustParseGeometry(str string) *Geometry { +func MustParseGeometry(str string) Geometry { g, err := ParseGeometry(str) if err != nil { panic(err) @@ -157,35 +157,35 @@ func MustParseGeometry(str string) *Geometry { // ParseGeometryFromEWKT parses the EWKT into a Geometry. func ParseGeometryFromEWKT( ewkt geopb.EWKT, srid geopb.SRID, defaultSRIDOverwriteSetting defaultSRIDOverwriteSetting, -) (*Geometry, error) { +) (Geometry, error) { g, err := parseEWKT(geopb.SpatialObjectType_GeometryType, ewkt, srid, defaultSRIDOverwriteSetting) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(g) + return MakeGeometry(g) } // ParseGeometryFromEWKB parses the EWKB into a Geometry. -func ParseGeometryFromEWKB(ewkb geopb.EWKB) (*Geometry, error) { +func ParseGeometryFromEWKB(ewkb geopb.EWKB) (Geometry, error) { g, err := parseEWKB(geopb.SpatialObjectType_GeometryType, ewkb, geopb.DefaultGeometrySRID, DefaultSRIDIsHint) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(g) + return MakeGeometry(g) } // ParseGeometryFromEWKBAndSRID parses the EWKB into a given Geometry with the given // SRID set. -func ParseGeometryFromEWKBAndSRID(ewkb geopb.EWKB, srid geopb.SRID) (*Geometry, error) { +func ParseGeometryFromEWKBAndSRID(ewkb geopb.EWKB, srid geopb.SRID) (Geometry, error) { g, err := parseEWKB(geopb.SpatialObjectType_GeometryType, ewkb, srid, DefaultSRIDShouldOverwrite) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(g) + return MakeGeometry(g) } // MustParseGeometryFromEWKB behaves as ParseGeometryFromEWKB, but panics if an error occurs. -func MustParseGeometryFromEWKB(ewkb geopb.EWKB) *Geometry { +func MustParseGeometryFromEWKB(ewkb geopb.EWKB) Geometry { ret, err := ParseGeometryFromEWKB(ewkb) if err != nil { panic(err) @@ -194,27 +194,27 @@ func MustParseGeometryFromEWKB(ewkb geopb.EWKB) *Geometry { } // ParseGeometryFromGeoJSON parses the GeoJSON into a given Geometry. -func ParseGeometryFromGeoJSON(json []byte) (*Geometry, error) { +func ParseGeometryFromGeoJSON(json []byte) (Geometry, error) { g, err := parseGeoJSON(geopb.SpatialObjectType_GeometryType, json, geopb.DefaultGeometrySRID) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(g) + return MakeGeometry(g) } // ParseGeometryFromEWKBUnsafe returns a new Geometry from an EWKB, without any SRID checks. // You should only do this if you trust the EWKB is setup correctly. // You most likely want geo.ParseGeometryFromEWKB instead. -func ParseGeometryFromEWKBUnsafe(ewkb geopb.EWKB) (*Geometry, error) { +func ParseGeometryFromEWKBUnsafe(ewkb geopb.EWKB) (Geometry, error) { base, err := parseEWKBRaw(geopb.SpatialObjectType_GeometryType, ewkb) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometryUnsafe(base), nil + return MakeGeometryUnsafe(base), nil } // AsGeography converts a given Geometry to its Geography form. -func (g *Geometry) AsGeography() (*Geography, error) { +func (g *Geometry) AsGeography() (Geography, error) { srid := g.SRID() if srid == 0 { // Set a geography SRID if one is not already set. @@ -222,19 +222,19 @@ func (g *Geometry) AsGeography() (*Geography, error) { } spatialObject, err := adjustSpatialObject(g.spatialObject, srid, geopb.SpatialObjectType_GeographyType) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(spatialObject) + return MakeGeography(spatialObject) } // CloneWithSRID sets a given Geometry's SRID to another, without any transformations. // Returns a new Geometry object. -func (g *Geometry) CloneWithSRID(srid geopb.SRID) (*Geometry, error) { +func (g *Geometry) CloneWithSRID(srid geopb.SRID) (Geometry, error) { spatialObject, err := adjustSpatialObject(g.spatialObject, srid, geopb.SpatialObjectType_GeometryType) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(spatialObject) + return MakeGeometry(spatialObject) } // adjustSpatialObject returns the SpatialObject with new parameters. @@ -337,7 +337,7 @@ func (g *Geometry) SpaceCurveIndex() uint64 { // Compare compares a Geometry against another. // It compares using SpaceCurveIndex, followed by the byte representation of the Geometry. // This must produce the same ordering as the index mechanism. -func (g *Geometry) Compare(o *Geometry) int { +func (g *Geometry) Compare(o Geometry) int { lhs := g.SpaceCurveIndex() rhs := o.SpaceCurveIndex() if lhs > rhs { @@ -358,42 +358,42 @@ type Geography struct { spatialObject geopb.SpatialObject } -// NewGeography returns a new Geography. Assumes the input EWKB is validated and in little endian. -func NewGeography(spatialObject geopb.SpatialObject) (*Geography, error) { +// MakeGeography returns a new Geography. Assumes the input EWKB is validated and in little endian. +func MakeGeography(spatialObject geopb.SpatialObject) (Geography, error) { projection, ok := geoprojbase.Projection(spatialObject.SRID) if !ok { - return nil, errors.Newf("unknown SRID for Geography: %d", spatialObject.SRID) + return Geography{}, errors.Newf("unknown SRID for Geography: %d", spatialObject.SRID) } if !projection.IsLatLng { - return nil, errors.Newf( + return Geography{}, errors.Newf( "SRID %d cannot be used for geography as it is not in a lon/lat coordinate system", spatialObject.SRID, ) } if spatialObject.Type != geopb.SpatialObjectType_GeographyType { - return nil, errors.Newf("expected geography type, found %s", spatialObject.Type) + return Geography{}, errors.Newf("expected geography type, found %s", spatialObject.Type) } - return &Geography{spatialObject: spatialObject}, nil + return Geography{spatialObject: spatialObject}, nil } -// NewGeographyUnsafe creates a geometry object that assumes spatialObject is from the DB. +// MakeGeographyUnsafe creates a geometry object that assumes spatialObject is from the DB. // It assumes the spatialObject underneath is safe. -func NewGeographyUnsafe(spatialObject geopb.SpatialObject) *Geography { - return &Geography{spatialObject: spatialObject} +func MakeGeographyUnsafe(spatialObject geopb.SpatialObject) Geography { + return Geography{spatialObject: spatialObject} } -// NewGeographyFromGeomT creates a new Geography from a geom.T object. -func NewGeographyFromGeomT(g geom.T) (*Geography, error) { +// MakeGeographyFromGeomT creates a new Geography from a geom.T object. +func MakeGeographyFromGeomT(g geom.T) (Geography, error) { spatialObject, err := spatialObjectFromGeomT(g, geopb.SpatialObjectType_GeographyType) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(spatialObject) + return MakeGeography(spatialObject) } -// MustNewGeographyFromGeomT enforces no error from NewGeographyFromGeomT. -func MustNewGeographyFromGeomT(g geom.T) *Geography { - ret, err := NewGeographyFromGeomT(g) +// MustMakeGeographyFromGeomT enforces no error from MakeGeographyFromGeomT. +func MustMakeGeographyFromGeomT(g geom.T) Geography { + ret, err := MakeGeographyFromGeomT(g) if err != nil { panic(err) } @@ -401,16 +401,16 @@ func MustNewGeographyFromGeomT(g geom.T) *Geography { } // ParseGeography parses a Geography from a given text. -func ParseGeography(str string) (*Geography, error) { +func ParseGeography(str string) (Geography, error) { spatialObject, err := parseAmbiguousText(geopb.SpatialObjectType_GeographyType, str, geopb.DefaultGeographySRID) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(spatialObject) + return MakeGeography(spatialObject) } // MustParseGeography behaves as ParseGeography, but panics if there is an error. -func MustParseGeography(str string) *Geography { +func MustParseGeography(str string) Geography { g, err := ParseGeography(str) if err != nil { panic(err) @@ -421,35 +421,35 @@ func MustParseGeography(str string) *Geography { // ParseGeographyFromEWKT parses the EWKT into a Geography. func ParseGeographyFromEWKT( ewkt geopb.EWKT, srid geopb.SRID, defaultSRIDOverwriteSetting defaultSRIDOverwriteSetting, -) (*Geography, error) { +) (Geography, error) { g, err := parseEWKT(geopb.SpatialObjectType_GeographyType, ewkt, srid, defaultSRIDOverwriteSetting) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(g) + return MakeGeography(g) } // ParseGeographyFromEWKB parses the EWKB into a Geography. -func ParseGeographyFromEWKB(ewkb geopb.EWKB) (*Geography, error) { +func ParseGeographyFromEWKB(ewkb geopb.EWKB) (Geography, error) { g, err := parseEWKB(geopb.SpatialObjectType_GeographyType, ewkb, geopb.DefaultGeographySRID, DefaultSRIDIsHint) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(g) + return MakeGeography(g) } // ParseGeographyFromEWKBAndSRID parses the EWKB into a given Geography with the // given SRID set. -func ParseGeographyFromEWKBAndSRID(ewkb geopb.EWKB, srid geopb.SRID) (*Geography, error) { +func ParseGeographyFromEWKBAndSRID(ewkb geopb.EWKB, srid geopb.SRID) (Geography, error) { g, err := parseEWKB(geopb.SpatialObjectType_GeographyType, ewkb, srid, DefaultSRIDShouldOverwrite) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(g) + return MakeGeography(g) } // MustParseGeographyFromEWKB behaves as ParseGeographyFromEWKB, but panics if an error occurs. -func MustParseGeographyFromEWKB(ewkb geopb.EWKB) *Geography { +func MustParseGeographyFromEWKB(ewkb geopb.EWKB) Geography { ret, err := ParseGeographyFromEWKB(ewkb) if err != nil { panic(err) @@ -458,42 +458,42 @@ func MustParseGeographyFromEWKB(ewkb geopb.EWKB) *Geography { } // ParseGeographyFromGeoJSON parses the GeoJSON into a given Geography. -func ParseGeographyFromGeoJSON(json []byte) (*Geography, error) { +func ParseGeographyFromGeoJSON(json []byte) (Geography, error) { g, err := parseGeoJSON(geopb.SpatialObjectType_GeographyType, json, geopb.DefaultGeographySRID) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(g) + return MakeGeography(g) } // ParseGeographyFromEWKBUnsafe returns a new Geography from an EWKB, without any SRID checks. // You should only do this if you trust the EWKB is setup correctly. // You most likely want ParseGeographyFromEWKB instead. -func ParseGeographyFromEWKBUnsafe(ewkb geopb.EWKB) (*Geography, error) { +func ParseGeographyFromEWKBUnsafe(ewkb geopb.EWKB) (Geography, error) { base, err := parseEWKBRaw(geopb.SpatialObjectType_GeographyType, ewkb) if err != nil { - return nil, err + return Geography{}, err } - return NewGeographyUnsafe(base), nil + return MakeGeographyUnsafe(base), nil } // CloneWithSRID sets a given Geography's SRID to another, without any transformations. // Returns a new Geography object. -func (g *Geography) CloneWithSRID(srid geopb.SRID) (*Geography, error) { +func (g *Geography) CloneWithSRID(srid geopb.SRID) (Geography, error) { spatialObject, err := adjustSpatialObject(g.spatialObject, srid, geopb.SpatialObjectType_GeographyType) if err != nil { - return nil, err + return Geography{}, err } - return NewGeography(spatialObject) + return MakeGeography(spatialObject) } // AsGeometry converts a given Geography to its Geometry form. -func (g *Geography) AsGeometry() (*Geometry, error) { +func (g *Geography) AsGeometry() (Geometry, error) { spatialObject, err := adjustSpatialObject(g.spatialObject, g.SRID(), geopb.SpatialObjectType_GeometryType) if err != nil { - return nil, err + return Geometry{}, err } - return NewGeometry(spatialObject) + return MakeGeometry(spatialObject) } // AsGeomT returns the Geography as a geom.T object. @@ -581,7 +581,7 @@ func (g *Geography) SpaceCurveIndex() uint64 { // Compare compares a Geography against another. // It compares using SpaceCurveIndex, followed by the byte representation of the Geography. // This must produce the same ordering as the index mechanism. -func (g *Geography) Compare(o *Geography) int { +func (g *Geography) Compare(o Geography) int { lhs := g.SpaceCurveIndex() rhs := o.SpaceCurveIndex() if lhs > rhs { diff --git a/pkg/geo/geo_test.go b/pkg/geo/geo_test.go index dfe331692ebe..518ae72a6df0 100644 --- a/pkg/geo/geo_test.go +++ b/pkg/geo/geo_test.go @@ -98,7 +98,7 @@ func mustDecodeEWKBFromString(t *testing.T, h string) geopb.EWKB { func TestGeospatialTypeFitsColumnMetadata(t *testing.T) { testCases := []struct { - t GeospatialType + t Geometry srid geopb.SRID shape geopb.ShapeType errorContains string @@ -113,7 +113,7 @@ func TestGeospatialTypeFitsColumnMetadata(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("%#v_fits_%d_%s", tc.t, tc.srid, tc.shape), func(t *testing.T) { - err := GeospatialTypeFitsColumnMetadata(tc.t, tc.srid, tc.shape) + err := GeospatialTypeFitsColumnMetadata(&tc.t, tc.srid, tc.shape) if tc.errorContains != "" { require.Error(t, err) require.Contains(t, err.Error(), tc.errorContains) diff --git a/pkg/geo/geogen/geogen.go b/pkg/geo/geogen/geogen.go index c37a3b231196..38d387b8e4da 100644 --- a/pkg/geo/geogen/geogen.go +++ b/pkg/geo/geogen/geogen.go @@ -184,7 +184,7 @@ func RandomGeomT( } // RandomGeometry generates a random Geometry with the given SRID. -func RandomGeometry(rng *rand.Rand, srid geopb.SRID) *geo.Geometry { +func RandomGeometry(rng *rand.Rand, srid geopb.SRID) geo.Geometry { minX, maxX := -math.MaxFloat32, math.MaxFloat32 minY, maxY := -math.MaxFloat32, math.MaxFloat32 proj, ok := geoprojbase.Projections[srid] @@ -192,7 +192,7 @@ func RandomGeometry(rng *rand.Rand, srid geopb.SRID) *geo.Geometry { minX, maxX = proj.Bounds.MinX, proj.Bounds.MaxX minY, maxY = proj.Bounds.MinY, proj.Bounds.MaxY } - ret, err := geo.NewGeometryFromGeomT(RandomGeomT(rng, minX, maxX, minY, maxY, srid)) + ret, err := geo.MakeGeometryFromGeomT(RandomGeomT(rng, minX, maxX, minY, maxY, srid)) if err != nil { panic(err) } @@ -200,11 +200,11 @@ func RandomGeometry(rng *rand.Rand, srid geopb.SRID) *geo.Geometry { } // RandomGeography generates a random Geometry with the given SRID. -func RandomGeography(rng *rand.Rand, srid geopb.SRID) *geo.Geography { +func RandomGeography(rng *rand.Rand, srid geopb.SRID) geo.Geography { // TODO(otan): generate geographies that traverse latitude/longitude boundaries. minX, maxX := -180.0, 180.0 minY, maxY := -90.0, 90.0 - ret, err := geo.NewGeographyFromGeomT(RandomGeomT(rng, minX, maxX, minY, maxY, srid)) + ret, err := geo.MakeGeographyFromGeomT(RandomGeomT(rng, minX, maxX, minY, maxY, srid)) if err != nil { panic(err) } diff --git a/pkg/geo/geogfn/azimuth.go b/pkg/geo/geogfn/azimuth.go index 38fd5391ca56..62ac7b5a8a18 100644 --- a/pkg/geo/geogfn/azimuth.go +++ b/pkg/geo/geogfn/azimuth.go @@ -24,9 +24,9 @@ import ( // North = 0; East = π/2; South = π; West = 3π/2. // Returns nil if the two points are the same. // Returns an error if any of the two Geography items are not points. -func Azimuth(a *geo.Geography, b *geo.Geography) (*float64, error) { +func Azimuth(a geo.Geography, b geo.Geography) (*float64, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return nil, geo.NewMismatchingSRIDsError(&a, &b) } aGeomT, err := a.AsGeomT() diff --git a/pkg/geo/geogfn/covers.go b/pkg/geo/geogfn/covers.go index 8decc8711425..aa7319b72824 100644 --- a/pkg/geo/geogfn/covers.go +++ b/pkg/geo/geogfn/covers.go @@ -39,15 +39,15 @@ import ( // 'multipolygon(((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 1.0, 0.0 0.0)), ((1.0 0.0, 2.0 0.0, 2.0 1.0, 1.0 1.0, 1.0 0.0)))', // 'linestring(0.0 0.0, 2.0 0.0)'::geography // ); -func Covers(a *geo.Geography, b *geo.Geography) (bool, error) { +func Covers(a geo.Geography, b geo.Geography) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } return covers(a, b) } // covers is the internal calculation for Covers. -func covers(a *geo.Geography, b *geo.Geography) (bool, error) { +func covers(a geo.Geography, b geo.Geography) (bool, error) { // Rect "contains" is a version of covers. if !a.BoundingRect().Contains(b.BoundingRect()) { return false, nil @@ -92,9 +92,9 @@ func covers(a *geo.Geography, b *geo.Geography) (bool, error) { // CoveredBy returns whether geography A is covered by geography B. // See Covers for limitations. -func CoveredBy(a *geo.Geography, b *geo.Geography) (bool, error) { +func CoveredBy(a geo.Geography, b geo.Geography) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } return covers(b, a) } diff --git a/pkg/geo/geogfn/distance.go b/pkg/geo/geogfn/distance.go index 7cb44bab9ef6..3ab34cc93360 100644 --- a/pkg/geo/geogfn/distance.go +++ b/pkg/geo/geogfn/distance.go @@ -30,10 +30,10 @@ const SpheroidErrorFraction = 0.05 // Distance returns the distance between geographies a and b on a sphere or spheroid. // Returns a geo.EmptyGeometryError if any of the Geographies are EMPTY. func Distance( - a *geo.Geography, b *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid, + a geo.Geography, b geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid, ) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(a, b) + return 0, geo.NewMismatchingSRIDsError(&a, &b) } aRegions, err := a.AsS2(geo.EmptyBehaviorError) diff --git a/pkg/geo/geogfn/dwithin.go b/pkg/geo/geogfn/dwithin.go index eb67a9070d0f..2da44dc294bb 100644 --- a/pkg/geo/geogfn/dwithin.go +++ b/pkg/geo/geogfn/dwithin.go @@ -21,14 +21,14 @@ import ( // equivalent to Distance(a, b) <= d. Otherwise, DWithin is instead equivalent // to Distance(a, b) < d. func DWithin( - a *geo.Geography, - b *geo.Geography, + a geo.Geography, + b geo.Geography, distance float64, useSphereOrSpheroid UseSphereOrSpheroid, exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if distance < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") diff --git a/pkg/geo/geogfn/intersects.go b/pkg/geo/geogfn/intersects.go index 397be2863cad..fcf7bc3919b1 100644 --- a/pkg/geo/geogfn/intersects.go +++ b/pkg/geo/geogfn/intersects.go @@ -20,12 +20,12 @@ import ( // Intersects returns whether geography A intersects geography B. // This calculation is done on the sphere. // Precision of intersect measurements is up to 1cm. -func Intersects(a *geo.Geography, b *geo.Geography) (bool, error) { +func Intersects(a geo.Geography, b geo.Geography) (bool, error) { if !a.BoundingRect().Intersects(b.BoundingRect()) { return false, nil } if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } aRegions, err := a.AsS2(geo.EmptyBehaviorOmit) diff --git a/pkg/geo/geogfn/segmentize.go b/pkg/geo/geogfn/segmentize.go index 2883067f3a8f..fa71942a0fa4 100644 --- a/pkg/geo/geogfn/segmentize.go +++ b/pkg/geo/geogfn/segmentize.go @@ -24,30 +24,30 @@ import ( // that given maximum segment length. // This works by dividing each segment by a power of 2 to find the // smallest power less than or equal to the segmentMaxLength. -func Segmentize(geography *geo.Geography, segmentMaxLength float64) (*geo.Geography, error) { +func Segmentize(geography geo.Geography, segmentMaxLength float64) (geo.Geography, error) { geometry, err := geography.AsGeomT() if err != nil { - return nil, err + return geo.Geography{}, err } switch geometry := geometry.(type) { case *geom.Point, *geom.MultiPoint: return geography, nil default: if segmentMaxLength <= 0 { - return nil, errors.Newf("maximum segment length must be positive") + return geo.Geography{}, errors.Newf("maximum segment length must be positive") } spheroid, err := geography.Spheroid() if err != nil { - return nil, err + return geo.Geography{}, err } // Convert segmentMaxLength to Angle with respect to earth sphere as // further calculation is done considering segmentMaxLength as Angle. segmentMaxAngle := segmentMaxLength / spheroid.SphereRadius segGeometry, err := geosegmentize.SegmentizeGeom(geometry, segmentMaxAngle, segmentizeCoords) if err != nil { - return nil, err + return geo.Geography{}, err } - return geo.NewGeographyFromGeomT(segGeometry) + return geo.MakeGeographyFromGeomT(segGeometry) } } diff --git a/pkg/geo/geogfn/topology_operations.go b/pkg/geo/geogfn/topology_operations.go index 053c93bae170..f6332ccda183 100644 --- a/pkg/geo/geogfn/topology_operations.go +++ b/pkg/geo/geogfn/topology_operations.go @@ -35,27 +35,27 @@ import ( // actual projection in the Spherical surface, which causes a small inaccuracies. // This inaccuracy will eventually grow if there is a substantial // number of a triangle with a larger area. -func Centroid(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (*geo.Geography, error) { +func Centroid(g geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (geo.Geography, error) { geomRepr, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geography{}, err } if geomRepr.Empty() { - return geo.NewGeographyFromGeomT(geom.NewGeometryCollection().SetSRID(geomRepr.SRID())) + return geo.MakeGeographyFromGeomT(geom.NewGeometryCollection().SetSRID(geomRepr.SRID())) } switch geomRepr.(type) { case *geom.Point, *geom.LineString, *geom.Polygon, *geom.MultiPoint, *geom.MultiLineString, *geom.MultiPolygon: default: - return nil, errors.Newf("unhandled geography type %s", g.ShapeType().String()) + return geo.Geography{}, errors.Newf("unhandled geography type %s", g.ShapeType().String()) } regions, err := geo.S2RegionsFromGeomT(geomRepr, geo.EmptyBehaviorOmit) if err != nil { - return nil, err + return geo.Geography{}, err } spheroid, err := g.Spheroid() if err != nil { - return nil, err + return geo.Geography{}, err } // localWeightedCentroids is the collection of all the centroid corresponds to @@ -118,5 +118,5 @@ func Centroid(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (*geo.G } latLng := s2.LatLngFromPoint(s2.Point{Vector: centroidVector.Normalize()}) centroid := geom.NewPointFlat(geom.XY, []float64{latLng.Lng.Degrees(), latLng.Lat.Degrees()}).SetSRID(int(g.SRID())) - return geo.NewGeographyFromGeomT(centroid) + return geo.MakeGeographyFromGeomT(centroid) } diff --git a/pkg/geo/geogfn/unary_operators.go b/pkg/geo/geogfn/unary_operators.go index 5e5e6310536a..a7d4804df6b4 100644 --- a/pkg/geo/geogfn/unary_operators.go +++ b/pkg/geo/geogfn/unary_operators.go @@ -22,7 +22,7 @@ import ( ) // Area returns the area of a given Geography. -func Area(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { +func Area(g geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { regions, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { return 0, err @@ -57,7 +57,7 @@ func Area(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, e } // Perimeter returns the perimeter of a given Geography. -func Perimeter(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { +func Perimeter(g geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { gt, err := g.AsGeomT() if err != nil { return 0, err @@ -81,7 +81,7 @@ func Perimeter(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float } // Length returns length of a given Geography. -func Length(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { +func Length(g geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, error) { gt, err := g.AsGeomT() if err != nil { return 0, err @@ -105,20 +105,20 @@ func Length(g *geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid) (float64, } // Project returns calculate a projected point given a source point, a distance and a azimuth. -func Project(g *geo.Geography, distance float64, azimuth s1.Angle) (*geo.Geography, error) { +func Project(g geo.Geography, distance float64, azimuth s1.Angle) (geo.Geography, error) { geomT, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geography{}, err } point, ok := geomT.(*geom.Point) if !ok { - return nil, errors.Newf("ST_Project(geography) is only valid for point inputs") + return geo.Geography{}, errors.Newf("ST_Project(geography) is only valid for point inputs") } spheroid, err := g.Spheroid() if err != nil { - return nil, err + return geo.Geography{}, err } // Normalize distance to be positive. @@ -132,11 +132,11 @@ func Project(g *geo.Geography, distance float64, azimuth s1.Angle) (*geo.Geograp // Check the distance validity. if distance > (math.Pi * spheroid.Radius) { - return nil, errors.Newf("distance must not be greater than %f", math.Pi*spheroid.Radius) + return geo.Geography{}, errors.Newf("distance must not be greater than %f", math.Pi*spheroid.Radius) } if point.Empty() { - return nil, errors.Newf("cannot project POINT EMPTY") + return geo.Geography{}, errors.Newf("cannot project POINT EMPTY") } // Convert to ta geodetic point. @@ -156,7 +156,7 @@ func Project(g *geo.Geography, distance float64, azimuth s1.Angle) (*geo.Geograp geo.NormalizeLatitudeDegrees(projected.Lat.Degrees()), }, ).SetSRID(point.SRID()) - return geo.NewGeographyFromGeomT(ret) + return geo.MakeGeographyFromGeomT(ret) } // length returns the sum of the lengtsh and perimeters in the shapes of the Geography. diff --git a/pkg/geo/geogfn/unary_operators_test.go b/pkg/geo/geogfn/unary_operators_test.go index f96f2b9cdc8e..9b1c4d6f1835 100644 --- a/pkg/geo/geogfn/unary_operators_test.go +++ b/pkg/geo/geogfn/unary_operators_test.go @@ -245,24 +245,24 @@ func TestLength(t *testing.T) { func TestProject(t *testing.T) { var testCases = []struct { desc string - point *geo.Geography + point geo.Geography distance float64 azimuth float64 - projected *geo.Geography + projected geo.Geography }{ { "POINT(0 0), 100000, radians(45)", - geo.MustNewGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0, 0}).SetSRID(4326)), + geo.MustMakeGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0, 0}).SetSRID(4326)), 100000, 45 * math.Pi / 180.0, - geo.MustNewGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0.6352310291255374, 0.6394723347291977}).SetSRID(4326)), + geo.MustMakeGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0.6352310291255374, 0.6394723347291977}).SetSRID(4326)), }, { "SRID=4004;POINT(0 0), 100000, radians(45)", - geo.MustNewGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0, 0}).SetSRID(4004)), + geo.MustMakeGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0, 0}).SetSRID(4004)), 100000, 45 * math.Pi / 180.0, - geo.MustNewGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0.6353047281438549, 0.6395336363116583}).SetSRID(4004)), + geo.MustMakeGeographyFromGeomT(geom.NewPointFlat(geom.XY, []float64{0.6353047281438549, 0.6395336363116583}).SetSRID(4004)), }, } diff --git a/pkg/geo/geoindex/geoindex.go b/pkg/geo/geoindex/geoindex.go index 7662e25422d5..027609c8fd07 100644 --- a/pkg/geo/geoindex/geoindex.go +++ b/pkg/geo/geoindex/geoindex.go @@ -115,7 +115,7 @@ var CommuteRelationshipMap = map[RelationshipType]RelationshipType{ type GeographyIndex interface { // InvertedIndexKeys returns the keys to store this object under when adding // it to the index. - InvertedIndexKeys(c context.Context, g *geo.Geography) ([]Key, error) + InvertedIndexKeys(c context.Context, g geo.Geography) ([]Key, error) // Acceleration for topological relationships (see // https://postgis.net/docs/reference.html#Spatial_Relationships). Distance @@ -127,34 +127,34 @@ type GeographyIndex interface { // Covers returns the index spans to read and union for the relationship // ST_Covers(g, x), where x are the indexed geometries. - Covers(c context.Context, g *geo.Geography) (UnionKeySpans, error) + Covers(c context.Context, g geo.Geography) (UnionKeySpans, error) // CoveredBy returns the index entries to read and the expression to compute // for ST_CoveredBy(g, x), where x are the indexed geometries. - CoveredBy(c context.Context, g *geo.Geography) (RPKeyExpr, error) + CoveredBy(c context.Context, g geo.Geography) (RPKeyExpr, error) // Intersects returns the index spans to read and union for the relationship // ST_Intersects(g, x), where x are the indexed geometries. - Intersects(c context.Context, g *geo.Geography) (UnionKeySpans, error) + Intersects(c context.Context, g geo.Geography) (UnionKeySpans, error) // DWithin returns the index spans to read and union for the relationship // ST_DWithin(g, x, distanceMeters). That is, there exists a part of // geometry g that is within distanceMeters of x, where x is an indexed // geometry. This function assumes a sphere. DWithin( - c context.Context, g *geo.Geography, distanceMeters float64, + c context.Context, g geo.Geography, distanceMeters float64, useSphereOrSpheroid geogfn.UseSphereOrSpheroid, ) (UnionKeySpans, error) // TestingInnerCovering returns an inner covering of g. - TestingInnerCovering(g *geo.Geography) s2.CellUnion + TestingInnerCovering(g geo.Geography) s2.CellUnion } // GeometryIndex is an index over 2D cartesian coordinates. type GeometryIndex interface { // InvertedIndexKeys returns the keys to store this object under when adding // it to the index. - InvertedIndexKeys(c context.Context, g *geo.Geometry) ([]Key, error) + InvertedIndexKeys(c context.Context, g geo.Geometry) ([]Key, error) // Acceleration for topological relationships (see // https://postgis.net/docs/reference.html#Spatial_Relationships). Distance @@ -166,29 +166,29 @@ type GeometryIndex interface { // Covers returns the index spans to read and union for the relationship // ST_Covers(g, x), where x are the indexed geometries. - Covers(c context.Context, g *geo.Geometry) (UnionKeySpans, error) + Covers(c context.Context, g geo.Geometry) (UnionKeySpans, error) // CoveredBy returns the index entries to read and the expression to compute // for ST_CoveredBy(g, x), where x are the indexed geometries. - CoveredBy(c context.Context, g *geo.Geometry) (RPKeyExpr, error) + CoveredBy(c context.Context, g geo.Geometry) (RPKeyExpr, error) // Intersects returns the index spans to read and union for the relationship // ST_Intersects(g, x), where x are the indexed geometries. - Intersects(c context.Context, g *geo.Geometry) (UnionKeySpans, error) + Intersects(c context.Context, g geo.Geometry) (UnionKeySpans, error) // DWithin returns the index spans to read and union for the relationship // ST_DWithin(g, x, distance). That is, there exists a part of geometry g // that is within distance units of x, where x is an indexed geometry. - DWithin(c context.Context, g *geo.Geometry, distance float64) (UnionKeySpans, error) + DWithin(c context.Context, g geo.Geometry, distance float64) (UnionKeySpans, error) // DFullyWithin returns the index spans to read and union for the // relationship ST_DFullyWithin(g, x, distance). That is, the maximum distance // across every pair of points comprising geometries g and x is within distance // units, where x is an indexed geometry. - DFullyWithin(c context.Context, g *geo.Geometry, distance float64) (UnionKeySpans, error) + DFullyWithin(c context.Context, g geo.Geometry, distance float64) (UnionKeySpans, error) // TestingInnerCovering returns an inner covering of g. - TestingInnerCovering(g *geo.Geometry) s2.CellUnion + TestingInnerCovering(g geo.Geometry) s2.CellUnion } // RelationshipType stores a type of geospatial relationship query that can diff --git a/pkg/geo/geoindex/s2_geography_index.go b/pkg/geo/geoindex/s2_geography_index.go index a3b6e13790a0..5dcc2ca3ea6e 100644 --- a/pkg/geo/geoindex/s2_geography_index.go +++ b/pkg/geo/geoindex/s2_geography_index.go @@ -60,7 +60,7 @@ func DefaultGeographyIndexConfig() *Config { // box of g to compute the covering. type geogCovererWithBBoxFallback struct { rc *s2.RegionCoverer - g *geo.Geography + g geo.Geography } var _ covererInterface = geogCovererWithBBoxFallback{} @@ -108,7 +108,7 @@ func isBadGeogCovering(cu s2.CellUnion) bool { } // InvertedIndexKeys implements the GeographyIndex interface. -func (i *s2GeographyIndex) InvertedIndexKeys(c context.Context, g *geo.Geography) ([]Key, error) { +func (i *s2GeographyIndex) InvertedIndexKeys(c context.Context, g geo.Geography) ([]Key, error) { r, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { return nil, err @@ -117,7 +117,7 @@ func (i *s2GeographyIndex) InvertedIndexKeys(c context.Context, g *geo.Geography } // Covers implements the GeographyIndex interface. -func (i *s2GeographyIndex) Covers(c context.Context, g *geo.Geography) (UnionKeySpans, error) { +func (i *s2GeographyIndex) Covers(c context.Context, g geo.Geography) (UnionKeySpans, error) { r, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { return nil, err @@ -126,7 +126,7 @@ func (i *s2GeographyIndex) Covers(c context.Context, g *geo.Geography) (UnionKey } // CoveredBy implements the GeographyIndex interface. -func (i *s2GeographyIndex) CoveredBy(c context.Context, g *geo.Geography) (RPKeyExpr, error) { +func (i *s2GeographyIndex) CoveredBy(c context.Context, g geo.Geography) (RPKeyExpr, error) { r, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { return nil, err @@ -135,7 +135,7 @@ func (i *s2GeographyIndex) CoveredBy(c context.Context, g *geo.Geography) (RPKey } // Intersects implements the GeographyIndex interface. -func (i *s2GeographyIndex) Intersects(c context.Context, g *geo.Geography) (UnionKeySpans, error) { +func (i *s2GeographyIndex) Intersects(c context.Context, g geo.Geography) (UnionKeySpans, error) { r, err := g.AsS2(geo.EmptyBehaviorOmit) if err != nil { return nil, err @@ -145,7 +145,7 @@ func (i *s2GeographyIndex) Intersects(c context.Context, g *geo.Geography) (Unio func (i *s2GeographyIndex) DWithin( _ context.Context, - g *geo.Geography, + g geo.Geography, distanceMeters float64, useSphereOrSpheroid geogfn.UseSphereOrSpheroid, ) (UnionKeySpans, error) { @@ -195,7 +195,7 @@ func (i *s2GeographyIndex) DWithin( return intersectsUsingCovering(covering), nil } -func (i *s2GeographyIndex) TestingInnerCovering(g *geo.Geography) s2.CellUnion { +func (i *s2GeographyIndex) TestingInnerCovering(g geo.Geography) s2.CellUnion { r, _ := g.AsS2(geo.EmptyBehaviorOmit) if r == nil { return nil diff --git a/pkg/geo/geoindex/s2_geography_index_test.go b/pkg/geo/geoindex/s2_geography_index_test.go index 907d4cf037af..7849b2c4d4f0 100644 --- a/pkg/geo/geoindex/s2_geography_index_test.go +++ b/pkg/geo/geoindex/s2_geography_index_test.go @@ -32,7 +32,7 @@ func TestS2GeographyIndexBasic(t *testing.T) { ctx := context.Background() var index GeographyIndex - shapes := make(map[string]*geo.Geography) + shapes := make(map[string]geo.Geography) datadriven.RunTest(t, "testdata/s2_geography", func(t *testing.T, d *datadriven.TestData) string { switch d.Cmd { case "init": diff --git a/pkg/geo/geoindex/s2_geometry_index.go b/pkg/geo/geoindex/s2_geometry_index.go index c6c9f6156b21..6ef83a0b7611 100644 --- a/pkg/geo/geoindex/s2_geometry_index.go +++ b/pkg/geo/geoindex/s2_geometry_index.go @@ -172,7 +172,7 @@ func isBadGeomCovering(cu s2.CellUnion) bool { } // InvertedIndexKeys implements the GeometryIndex interface. -func (s *s2GeometryIndex) InvertedIndexKeys(c context.Context, g *geo.Geometry) ([]Key, error) { +func (s *s2GeometryIndex) InvertedIndexKeys(c context.Context, g geo.Geometry) ([]Key, error) { // If the geometry exceeds the bounds, we index the clipped geometry in // addition to the special cell, so that queries for geometries that don't // exceed the bounds don't need to query the special cell (which would @@ -193,12 +193,12 @@ func (s *s2GeometryIndex) InvertedIndexKeys(c context.Context, g *geo.Geometry) } // Covers implements the GeometryIndex interface. -func (s *s2GeometryIndex) Covers(c context.Context, g *geo.Geometry) (UnionKeySpans, error) { +func (s *s2GeometryIndex) Covers(c context.Context, g geo.Geometry) (UnionKeySpans, error) { return s.Intersects(c, g) } // CoveredBy implements the GeometryIndex interface. -func (s *s2GeometryIndex) CoveredBy(c context.Context, g *geo.Geometry) (RPKeyExpr, error) { +func (s *s2GeometryIndex) CoveredBy(c context.Context, g geo.Geometry) (RPKeyExpr, error) { // If the geometry exceeds the bounds, we use the clipped geometry to // restrict the search within the bounds. gt, clipped, err := s.convertToGeomTAndTryClip(g) @@ -221,7 +221,7 @@ func (s *s2GeometryIndex) CoveredBy(c context.Context, g *geo.Geometry) (RPKeyEx } // Intersects implements the GeometryIndex interface. -func (s *s2GeometryIndex) Intersects(c context.Context, g *geo.Geometry) (UnionKeySpans, error) { +func (s *s2GeometryIndex) Intersects(c context.Context, g geo.Geometry) (UnionKeySpans, error) { // If the geometry exceeds the bounds, we use the clipped geometry to // restrict the search within the bounds. gt, clipped, err := s.convertToGeomTAndTryClip(g) @@ -242,7 +242,7 @@ func (s *s2GeometryIndex) Intersects(c context.Context, g *geo.Geometry) (UnionK } func (s *s2GeometryIndex) DWithin( - c context.Context, g *geo.Geometry, distance float64, + c context.Context, g geo.Geometry, distance float64, ) (UnionKeySpans, error) { // TODO(sumeer): are the default params the correct thing to use here? g, err := geomfn.Buffer(g, geomfn.MakeDefaultBufferParams(), distance) @@ -253,7 +253,7 @@ func (s *s2GeometryIndex) DWithin( } func (s *s2GeometryIndex) DFullyWithin( - c context.Context, g *geo.Geometry, distance float64, + c context.Context, g geo.Geometry, distance float64, ) (UnionKeySpans, error) { // TODO(sumeer): are the default params the correct thing to use here? g, err := geomfn.Buffer(g, geomfn.MakeDefaultBufferParams(), distance) @@ -264,7 +264,7 @@ func (s *s2GeometryIndex) DFullyWithin( } // Converts to geom.T and clips to the rectangle bounds of the index. -func (s *s2GeometryIndex) convertToGeomTAndTryClip(g *geo.Geometry) (geom.T, bool, error) { +func (s *s2GeometryIndex) convertToGeomTAndTryClip(g geo.Geometry) (geom.T, bool, error) { gt, err := g.AsGeomT() if err != nil { return nil, false, err @@ -286,9 +286,6 @@ func (s *s2GeometryIndex) convertToGeomTAndTryClip(g *geo.Geometry) (geom.T, boo if err != nil { return nil, false, err } - if g == nil { - return nil, false, errors.Errorf("internal error: clippedWKB cannot be parsed") - } gt, err = g.AsGeomT() if err != nil { return nil, false, err @@ -449,7 +446,7 @@ func (s *s2GeometryIndex) s2RegionsFromPlanarGeomT(geomRepr geom.T) []s2.Region return regions } -func (s *s2GeometryIndex) TestingInnerCovering(g *geo.Geometry) s2.CellUnion { +func (s *s2GeometryIndex) TestingInnerCovering(g geo.Geometry) s2.CellUnion { gt, _, err := s.convertToGeomTAndTryClip(g) if err != nil || gt == nil { return nil diff --git a/pkg/geo/geoindex/s2_geometry_index_test.go b/pkg/geo/geoindex/s2_geometry_index_test.go index 10968677ddc4..4c59a7bd39be 100644 --- a/pkg/geo/geoindex/s2_geometry_index_test.go +++ b/pkg/geo/geoindex/s2_geometry_index_test.go @@ -29,7 +29,7 @@ func TestS2GeometryIndexBasic(t *testing.T) { ctx := context.Background() var index GeometryIndex - shapes := make(map[string]*geo.Geometry) + shapes := make(map[string]geo.Geometry) datadriven.RunTest(t, "testdata/s2_geometry", func(t *testing.T, d *datadriven.TestData) string { switch d.Cmd { case "init": @@ -81,7 +81,7 @@ func TestS2GeometryIndexBasic(t *testing.T) { func TestClipByRect(t *testing.T) { defer leaktest.AfterTest(t)() - var g *geo.Geometry + var g geo.Geometry var err error datadriven.RunTest(t, "testdata/clip", func(t *testing.T, d *datadriven.TestData) string { switch d.Cmd { @@ -138,7 +138,7 @@ func TestNoClippingAtSRIDBounds(t *testing.T) { xCorners := []float64{b.MinX, b.MinX, b.MaxX, b.MaxX} yCorners := []float64{b.MinY, b.MaxY, b.MaxY, b.MinY} for i := range xCorners { - g, err := geo.NewGeometryFromPointCoords(xCorners[i], yCorners[i]) + g, err := geo.MakeGeometryFromPointCoords(xCorners[i], yCorners[i]) require.NoError(t, err) keys, err := index.InvertedIndexKeys(context.Background(), g) require.NoError(t, err) diff --git a/pkg/geo/geomfn/azimuth.go b/pkg/geo/geomfn/azimuth.go index 1497a64c8648..b1c998555cfe 100644 --- a/pkg/geo/geomfn/azimuth.go +++ b/pkg/geo/geomfn/azimuth.go @@ -25,9 +25,9 @@ import ( // See https://en.wikipedia.org/wiki/Polar_coordinate_system. // Returns nil if the two points are the same. // Returns an error if any of the two Geometry items are not points. -func Azimuth(a *geo.Geometry, b *geo.Geometry) (*float64, error) { +func Azimuth(a geo.Geometry, b geo.Geometry) (*float64, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return nil, geo.NewMismatchingSRIDsError(&a, &b) } aGeomT, err := a.AsGeomT() diff --git a/pkg/geo/geomfn/binary_predicates.go b/pkg/geo/geomfn/binary_predicates.go index 55916ce59c79..dabee8b40b40 100644 --- a/pkg/geo/geomfn/binary_predicates.go +++ b/pkg/geo/geomfn/binary_predicates.go @@ -16,9 +16,9 @@ import ( ) // Covers returns whether geometry A covers geometry B. -func Covers(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Covers(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -27,9 +27,9 @@ func Covers(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // CoveredBy returns whether geometry A is covered by geometry B. -func CoveredBy(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func CoveredBy(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !b.CartesianBoundingBox().Covers(a.CartesianBoundingBox()) { return false, nil @@ -38,9 +38,9 @@ func CoveredBy(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Contains returns whether geometry A contains geometry B. -func Contains(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Contains(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -49,9 +49,9 @@ func Contains(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // ContainsProperly returns whether geometry A properly contains geometry B. -func ContainsProperly(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func ContainsProperly(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -60,9 +60,9 @@ func ContainsProperly(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Crosses returns whether geometry A crosses geometry B. -func Crosses(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Crosses(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -71,17 +71,17 @@ func Crosses(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Disjoint returns whether geometry A is disjoint from geometry B. -func Disjoint(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Disjoint(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } return geos.Disjoint(a.EWKB(), b.EWKB()) } // Equals returns whether geometry A equals geometry B. -func Equals(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Equals(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } // Empty items are equal to each other. // Do this check before the BoundingBoxIntersects check, as we would otherwise @@ -96,9 +96,9 @@ func Equals(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Intersects returns whether geometry A intersects geometry B. -func Intersects(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Intersects(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -107,9 +107,9 @@ func Intersects(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Overlaps returns whether geometry A overlaps geometry B. -func Overlaps(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Overlaps(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -118,9 +118,9 @@ func Overlaps(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Touches returns whether geometry A touches geometry B. -func Touches(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Touches(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -129,9 +129,9 @@ func Touches(a *geo.Geometry, b *geo.Geometry) (bool, error) { } // Within returns whether geometry A is within geometry B. -func Within(a *geo.Geometry, b *geo.Geometry) (bool, error) { +func Within(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if !b.CartesianBoundingBox().Covers(a.CartesianBoundingBox()) { return false, nil diff --git a/pkg/geo/geomfn/binary_predicates_test.go b/pkg/geo/geomfn/binary_predicates_test.go index 1ab7d2230d4c..32e7ffe37173 100644 --- a/pkg/geo/geomfn/binary_predicates_test.go +++ b/pkg/geo/geomfn/binary_predicates_test.go @@ -31,8 +31,8 @@ var ( func TestCovers(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, true}, @@ -56,8 +56,8 @@ func TestCovers(t *testing.T) { func TestCoveredBy(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, @@ -81,8 +81,8 @@ func TestCoveredBy(t *testing.T) { func TestContains(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, true}, @@ -108,8 +108,8 @@ func TestContains(t *testing.T) { func TestContainsProperly(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRect, false}, @@ -133,8 +133,8 @@ func TestContainsProperly(t *testing.T) { func TestCrosses(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, @@ -160,8 +160,8 @@ func TestCrosses(t *testing.T) { func TestDisjoint(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, @@ -184,8 +184,8 @@ func TestDisjoint(t *testing.T) { func TestEquals(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {emptyLine, emptyRect, true}, @@ -213,8 +213,8 @@ func TestEquals(t *testing.T) { func TestIntersects(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, leftRectPoint, false}, @@ -241,8 +241,8 @@ func TestIntersects(t *testing.T) { func TestOverlaps(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, @@ -267,8 +267,8 @@ func TestOverlaps(t *testing.T) { func TestTouches(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, @@ -292,8 +292,8 @@ func TestTouches(t *testing.T) { func TestWithin(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected bool }{ {rightRect, rightRectPoint, false}, diff --git a/pkg/geo/geomfn/buffer.go b/pkg/geo/geomfn/buffer.go index ca930bfbb2ce..e3cb0f879419 100644 --- a/pkg/geo/geomfn/buffer.go +++ b/pkg/geo/geomfn/buffer.go @@ -112,10 +112,10 @@ func ParseBufferParams(s string, distance float64) (BufferParams, float64, error } // Buffer buffers a given Geometry by the supplied parameters. -func Buffer(g *geo.Geometry, params BufferParams, distance float64) (*geo.Geometry, error) { +func Buffer(g geo.Geometry, params BufferParams, distance float64) (geo.Geometry, error) { bufferedGeom, err := geos.Buffer(g.EWKB(), params.p, distance) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(bufferedGeom) } diff --git a/pkg/geo/geomfn/collections.go b/pkg/geo/geomfn/collections.go index b81b41c8b3cb..930e70576334 100644 --- a/pkg/geo/geomfn/collections.go +++ b/pkg/geo/geomfn/collections.go @@ -19,11 +19,11 @@ import ( // CollectionExtract returns a (multi-)geometry consisting only of the specified type. // The type can only be point, line, or polygon. -func CollectionExtract(g *geo.Geometry, shapeType geopb.ShapeType) (*geo.Geometry, error) { +func CollectionExtract(g geo.Geometry, shapeType geopb.ShapeType) (geo.Geometry, error) { switch shapeType { case geopb.ShapeType_Point, geopb.ShapeType_LineString, geopb.ShapeType_Polygon: default: - return nil, errors.Newf("only point, linestring and polygon may be extracted (got %s)", + return geo.Geometry{}, errors.Newf("only point, linestring and polygon may be extracted (got %s)", shapeType) } @@ -35,7 +35,7 @@ func CollectionExtract(g *geo.Geometry, shapeType geopb.ShapeType) (*geo.Geometr t, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } switch t := t.(type) { @@ -43,26 +43,26 @@ func CollectionExtract(g *geo.Geometry, shapeType geopb.ShapeType) (*geo.Geometr case *geom.Point, *geom.LineString, *geom.Polygon: switch shapeType { case geopb.ShapeType_Point: - return geo.NewGeometryFromGeomT(geom.NewPointEmpty(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewPointEmpty(t.Layout()).SetSRID(t.SRID())) case geopb.ShapeType_LineString: - return geo.NewGeometryFromGeomT(geom.NewLineString(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewLineString(t.Layout()).SetSRID(t.SRID())) case geopb.ShapeType_Polygon: - return geo.NewGeometryFromGeomT(geom.NewPolygon(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewPolygon(t.Layout()).SetSRID(t.SRID())) default: - return nil, errors.AssertionFailedf("unexpected shape type %v", shapeType.String()) + return geo.Geometry{}, errors.AssertionFailedf("unexpected shape type %v", shapeType.String()) } // If the input is a multitype then return an empty multi-geometry of the expected type. case *geom.MultiPoint, *geom.MultiLineString, *geom.MultiPolygon: switch shapeType.MultiType() { case geopb.ShapeType_MultiPoint: - return geo.NewGeometryFromGeomT(geom.NewMultiPoint(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewMultiPoint(t.Layout()).SetSRID(t.SRID())) case geopb.ShapeType_MultiLineString: - return geo.NewGeometryFromGeomT(geom.NewMultiLineString(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewMultiLineString(t.Layout()).SetSRID(t.SRID())) case geopb.ShapeType_MultiPolygon: - return geo.NewGeometryFromGeomT(geom.NewMultiPolygon(t.Layout()).SetSRID(t.SRID())) + return geo.MakeGeometryFromGeomT(geom.NewMultiPolygon(t.Layout()).SetSRID(t.SRID())) default: - return nil, errors.AssertionFailedf("unexpected shape type %v", shapeType.MultiType().String()) + return geo.Geometry{}, errors.AssertionFailedf("unexpected shape type %v", shapeType.MultiType().String()) } // If the input is a collection, recursively gather geometries of the right type. @@ -88,15 +88,15 @@ func CollectionExtract(g *geo.Geometry, shapeType geopb.ShapeType) (*geo.Geometr case geopb.ShapeType_Polygon: multi, err = collectionExtractPolygons(iter, layout, srid) default: - return nil, errors.AssertionFailedf("unexpected shape type %v", shapeType.String()) + return geo.Geometry{}, errors.AssertionFailedf("unexpected shape type %v", shapeType.String()) } if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(multi) + return geo.MakeGeometryFromGeomT(multi) default: - return nil, errors.AssertionFailedf("unexpected shape type: %T", t) + return geo.Geometry{}, errors.AssertionFailedf("unexpected shape type: %T", t) } } @@ -158,20 +158,20 @@ func collectionExtractPolygons( } // CollectionHomogenize returns the simplest representation of a collection. -func CollectionHomogenize(g *geo.Geometry) (*geo.Geometry, error) { +func CollectionHomogenize(g geo.Geometry) (geo.Geometry, error) { t, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } srid := t.SRID() t, err = collectionHomogenizeGeomT(t) if err != nil { - return nil, err + return geo.Geometry{}, err } if srid != 0 { geo.AdjustGeomTSRID(t, geopb.SRID(srid)) } - return geo.NewGeometryFromGeomT(t) + return geo.MakeGeometryFromGeomT(t) } // collectionHomogenizeGeomT homogenizes a geom.T collection. @@ -275,39 +275,39 @@ func collectionHomogenizeGeomT(t geom.T) (geom.T, error) { } // Multi converts the given geometry into a new multi-geometry. -func Multi(g *geo.Geometry) (*geo.Geometry, error) { +func Multi(g geo.Geometry) (geo.Geometry, error) { t, err := g.AsGeomT() // implicitly clones the input if err != nil { - return nil, err + return geo.Geometry{}, err } switch t := t.(type) { case *geom.MultiPoint, *geom.MultiLineString, *geom.MultiPolygon, *geom.GeometryCollection: - return geo.NewGeometryFromGeomT(t) + return geo.MakeGeometryFromGeomT(t) case *geom.Point: multi := geom.NewMultiPoint(t.Layout()).SetSRID(t.SRID()) if !t.Empty() { if err = multi.Push(t); err != nil { - return nil, err + return geo.Geometry{}, err } } - return geo.NewGeometryFromGeomT(multi) + return geo.MakeGeometryFromGeomT(multi) case *geom.LineString: multi := geom.NewMultiLineString(t.Layout()).SetSRID(t.SRID()) if !t.Empty() { if err = multi.Push(t); err != nil { - return nil, err + return geo.Geometry{}, err } } - return geo.NewGeometryFromGeomT(multi) + return geo.MakeGeometryFromGeomT(multi) case *geom.Polygon: multi := geom.NewMultiPolygon(t.Layout()).SetSRID(t.SRID()) if !t.Empty() { if err = multi.Push(t); err != nil { - return nil, err + return geo.Geometry{}, err } } - return geo.NewGeometryFromGeomT(multi) + return geo.MakeGeometryFromGeomT(multi) default: - return nil, errors.AssertionFailedf("unknown geometry type: %T", t) + return geo.Geometry{}, errors.AssertionFailedf("unknown geometry type: %T", t) } } diff --git a/pkg/geo/geomfn/de9im.go b/pkg/geo/geomfn/de9im.go index 00a79f17308e..7cb1bd334378 100644 --- a/pkg/geo/geomfn/de9im.go +++ b/pkg/geo/geomfn/de9im.go @@ -18,17 +18,17 @@ import ( ) // Relate returns the DE-9IM relation between A and B. -func Relate(a *geo.Geometry, b *geo.Geometry) (string, error) { +func Relate(a geo.Geometry, b geo.Geometry) (string, error) { if a.SRID() != b.SRID() { - return "", geo.NewMismatchingSRIDsError(a, b) + return "", geo.NewMismatchingSRIDsError(&a, &b) } return geos.Relate(a.EWKB(), b.EWKB()) } // RelatePattern returns whether the DE-9IM relation between A and B matches. -func RelatePattern(a *geo.Geometry, b *geo.Geometry, pattern string) (bool, error) { +func RelatePattern(a geo.Geometry, b geo.Geometry, pattern string) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } return geos.RelatePattern(a.EWKB(), b.EWKB(), pattern) } diff --git a/pkg/geo/geomfn/de9im_test.go b/pkg/geo/geomfn/de9im_test.go index 247b5ca7e8d1..6849b900dec1 100644 --- a/pkg/geo/geomfn/de9im_test.go +++ b/pkg/geo/geomfn/de9im_test.go @@ -20,8 +20,8 @@ import ( func TestRelate(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry expected string }{ {leftRect, rightRect, "FF2F11212"}, diff --git a/pkg/geo/geomfn/distance.go b/pkg/geo/geomfn/distance.go index 0b294720a10f..a117cb7bfe9b 100644 --- a/pkg/geo/geomfn/distance.go +++ b/pkg/geo/geomfn/distance.go @@ -35,18 +35,18 @@ const ( // MinDistance returns the minimum distance between geometries A and B. // This returns a geo.EmptyGeometryError if either A or B is EMPTY. -func MinDistance(a *geo.Geometry, b *geo.Geometry) (float64, error) { +func MinDistance(a geo.Geometry, b geo.Geometry) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(a, b) + return 0, geo.NewMismatchingSRIDsError(&a, &b) } return minDistanceInternal(a, b, 0, geo.EmptyBehaviorOmit, geo.FnInclusive) } // MaxDistance returns the maximum distance across every pair of points comprising // geometries A and B. -func MaxDistance(a *geo.Geometry, b *geo.Geometry) (float64, error) { +func MaxDistance(a geo.Geometry, b geo.Geometry) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(a, b) + return 0, geo.NewMismatchingSRIDsError(&a, &b) } return maxDistanceInternal(a, b, math.MaxFloat64, geo.EmptyBehaviorOmit, geo.FnInclusive) } @@ -55,10 +55,10 @@ func MaxDistance(a *geo.Geometry, b *geo.Geometry) (float64, error) { // If exclusive, DWithin is equivalent to Distance(a, b) < d. Otherwise, DWithin // is equivalent to Distance(a, b) <= d. func DWithin( - a *geo.Geometry, b *geo.Geometry, d float64, exclusivity geo.FnExclusivity, + a geo.Geometry, b geo.Geometry, d float64, exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if d < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") @@ -85,10 +85,10 @@ func DWithin( // DFullyWithin is equivalent to MaxDistance(a, b) < d. Otherwise, DFullyWithin // is equivalent to MaxDistance(a, b) <= d. func DFullyWithin( - a *geo.Geometry, b *geo.Geometry, d float64, exclusivity geo.FnExclusivity, + a geo.Geometry, b geo.Geometry, d float64, exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(a, b) + return false, geo.NewMismatchingSRIDsError(&a, &b) } if d < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") @@ -112,9 +112,9 @@ func DFullyWithin( // LongestLineString returns the LineString corresponds to maximum distance across // every pair of points comprising geometries A and B. -func LongestLineString(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) { +func LongestLineString(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) } u := newGeomMaxDistanceUpdater(math.MaxFloat64, geo.FnInclusive) return distanceLineStringInternal(a, b, u, geo.EmptyBehaviorOmit) @@ -122,9 +122,9 @@ func LongestLineString(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) // ShortestLineString returns the LineString corresponds to minimum distance across // every pair of points comprising geometries A and B. -func ShortestLineString(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) { +func ShortestLineString(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) } u := newGeomMinDistanceUpdater(0 /*stopAfter */, geo.FnInclusive) return distanceLineStringInternal(a, b, u, geo.EmptyBehaviorOmit) @@ -136,12 +136,12 @@ func ShortestLineString(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) // EmptyGeometryError if A or B contains only EMPTY geometries, even if emptyBehavior // is set to EmptyBehaviorOmit. func distanceLineStringInternal( - a *geo.Geometry, b *geo.Geometry, u geodist.DistanceUpdater, emptyBehavior geo.EmptyBehavior, -) (*geo.Geometry, error) { + a geo.Geometry, b geo.Geometry, u geodist.DistanceUpdater, emptyBehavior geo.EmptyBehavior, +) (geo.Geometry, error) { c := &geomDistanceCalculator{updater: u, boundingBoxIntersects: a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox())} _, err := distanceInternal(a, b, c, emptyBehavior) if err != nil { - return nil, err + return geo.Geometry{}, err } var coordA, coordB geom.Coord switch u := u.(type) { @@ -152,18 +152,18 @@ func distanceLineStringInternal( coordA = u.coordA coordB = u.coordB default: - return nil, errors.Newf("programmer error: unknown behavior") + return geo.Geometry{}, errors.Newf("programmer error: unknown behavior") } lineString := geom.NewLineStringFlat(geom.XY, append(coordA, coordB...)).SetSRID(int(a.SRID())) - return geo.NewGeometryFromGeomT(lineString) + return geo.MakeGeometryFromGeomT(lineString) } // maxDistanceInternal finds the maximum distance between two geometries. // We can re-use the same algorithm as min-distance, allowing skips of checks that involve // the interiors or intersections as those will always be less then the maximum min-distance. func maxDistanceInternal( - a *geo.Geometry, - b *geo.Geometry, + a geo.Geometry, + b geo.Geometry, stopAfter float64, emptyBehavior geo.EmptyBehavior, exclusivity geo.FnExclusivity, @@ -176,8 +176,8 @@ func maxDistanceInternal( // minDistanceInternal finds the minimum distance between two geometries. // This implementation is done in-house, as compared to using GEOS. func minDistanceInternal( - a *geo.Geometry, - b *geo.Geometry, + a geo.Geometry, + b geo.Geometry, stopAfter float64, emptyBehavior geo.EmptyBehavior, exclusivity geo.FnExclusivity, @@ -193,7 +193,7 @@ func minDistanceInternal( // EmptyGeometryError if A or B contains only EMPTY geometries, even if emptyBehavior // is set to EmptyBehaviorOmit. func distanceInternal( - a *geo.Geometry, b *geo.Geometry, c geodist.DistanceCalculator, emptyBehavior geo.EmptyBehavior, + a geo.Geometry, b geo.Geometry, c geodist.DistanceCalculator, emptyBehavior geo.EmptyBehavior, ) (float64, error) { // If either side has no geoms, then we error out regardless of emptyBehavior. if a.Empty() || b.Empty() { diff --git a/pkg/geo/geomfn/distance_test.go b/pkg/geo/geomfn/distance_test.go index 0455fcc0f577..101de91cb501 100644 --- a/pkg/geo/geomfn/distance_test.go +++ b/pkg/geo/geomfn/distance_test.go @@ -653,10 +653,9 @@ func TestLongestLineString(t *testing.T) { require.NoError(t, err) b, err := geo.ParseGeometry(tc.b) require.NoError(t, err) - longestLine, err := LongestLineString(a, b) + _, err = LongestLineString(a, b) require.Error(t, err) require.True(t, geo.IsEmptyGeometryError(err)) - require.Nil(t, longestLine) }) } }) diff --git a/pkg/geo/geomfn/envelope.go b/pkg/geo/geomfn/envelope.go index bc0371972f4e..34d2098c8fa3 100644 --- a/pkg/geo/geomfn/envelope.go +++ b/pkg/geo/geomfn/envelope.go @@ -15,9 +15,9 @@ import "github.com/cockroachdb/cockroach/pkg/geo" // Envelope forms an envelope (compliant with the OGC spec) of the given Geometry. // It uses the bounding box to return a Polygon, but can return a Point or // Line if the bounding box is degenerate and not a box. -func Envelope(g *geo.Geometry) (*geo.Geometry, error) { +func Envelope(g geo.Geometry) (geo.Geometry, error) { if g.Empty() { return g, nil } - return geo.NewGeometryFromGeomT(g.CartesianBoundingBox().ToGeomT(g.SRID())) + return geo.MakeGeometryFromGeomT(g.CartesianBoundingBox().ToGeomT(g.SRID())) } diff --git a/pkg/geo/geomfn/flip_coordinates.go b/pkg/geo/geomfn/flip_coordinates.go index 6c0c024a67c5..6696ee04ca56 100644 --- a/pkg/geo/geomfn/flip_coordinates.go +++ b/pkg/geo/geomfn/flip_coordinates.go @@ -16,22 +16,22 @@ import ( ) // FlipCoordinates returns a modified Geometry whose X, Y coordinates are flipped. -func FlipCoordinates(geometry *geo.Geometry) (*geo.Geometry, error) { +func FlipCoordinates(geometry geo.Geometry) (geo.Geometry, error) { if geometry.Empty() { return geometry, nil } g, err := geometry.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } g, err = flipCoordinates(g) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func flipCoordinates(g geom.T) (geom.T, error) { diff --git a/pkg/geo/geomfn/flip_coordinates_test.go b/pkg/geo/geomfn/flip_coordinates_test.go index e318ab4f6e67..106d6107c0c4 100644 --- a/pkg/geo/geomfn/flip_coordinates_test.go +++ b/pkg/geo/geomfn/flip_coordinates_test.go @@ -78,12 +78,12 @@ func TestFlipCoordinates(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) got, err := FlipCoordinates(geometry) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -119,7 +119,7 @@ func TestCollectionFlipCoordinates(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) geometry, err = FlipCoordinates(geometry) diff --git a/pkg/geo/geomfn/force.go b/pkg/geo/geomfn/force.go index c01fc2678050..b9b44fe99222 100644 --- a/pkg/geo/geomfn/force.go +++ b/pkg/geo/geomfn/force.go @@ -18,16 +18,16 @@ import ( // ForceLayout forces a geometry into the given layout. // If dimensions are added, 0 coordinates are padded to them. -func ForceLayout(g *geo.Geometry, layout geom.Layout) (*geo.Geometry, error) { +func ForceLayout(g geo.Geometry, layout geom.Layout) (geo.Geometry, error) { geomT, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } retGeomT, err := forceLayout(geomT, layout) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(retGeomT) + return geo.MakeGeometryFromGeomT(retGeomT) } // forceLayout forces a geom.T into the given layout. diff --git a/pkg/geo/geomfn/linear_reference.go b/pkg/geo/geomfn/linear_reference.go index e54c75c659bb..bc6fc70267ff 100644 --- a/pkg/geo/geomfn/linear_reference.go +++ b/pkg/geo/geomfn/linear_reference.go @@ -22,13 +22,13 @@ import ( // LineString which are at an integral multiples of given fraction of // LineString's total length. When repeat is set to false, it returns // the first point. -func LineInterpolatePoints(g *geo.Geometry, fraction float64, repeat bool) (*geo.Geometry, error) { +func LineInterpolatePoints(g geo.Geometry, fraction float64, repeat bool) (geo.Geometry, error) { if fraction < 0 || fraction > 1 { - return nil, errors.Newf("fraction %f should be within [0 1] range", fraction) + return geo.Geometry{}, errors.Newf("fraction %f should be within [0 1] range", fraction) } geomRepr, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } switch geomRepr := geomRepr.(type) { case *geom.LineString: @@ -41,25 +41,25 @@ func LineInterpolatePoints(g *geo.Geometry, fraction float64, repeat bool) (*geo for pointInserted := 1; pointInserted <= numberOfInterpolatedPoints; pointInserted++ { pointEWKB, err := geos.InterpolateLine(g.EWKB(), float64(pointInserted)*fraction*lengthOfLineString) if err != nil { - return nil, err + return geo.Geometry{}, err } point, err := ewkb.Unmarshal(pointEWKB) if err != nil { - return nil, err + return geo.Geometry{}, err } err = interpolatedPoints.Push(point.(*geom.Point)) if err != nil { - return nil, err + return geo.Geometry{}, err } } - return geo.NewGeometryFromGeomT(interpolatedPoints) + return geo.MakeGeometryFromGeomT(interpolatedPoints) } interpolatedPointEWKB, err := geos.InterpolateLine(g.EWKB(), fraction*lengthOfLineString) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(interpolatedPointEWKB) default: - return nil, errors.Newf("geometry %s should be LineString", g.ShapeType()) + return geo.Geometry{}, errors.Newf("geometry %s should be LineString", g.ShapeType()) } } diff --git a/pkg/geo/geomfn/linestring.go b/pkg/geo/geomfn/linestring.go index 3fbb1d0a1860..0aadf467e39f 100644 --- a/pkg/geo/geomfn/linestring.go +++ b/pkg/geo/geomfn/linestring.go @@ -17,35 +17,35 @@ import ( ) // SetPoint sets the point at the given index of lineString; index is 0-based. -func SetPoint(lineString *geo.Geometry, index int, point *geo.Geometry) (*geo.Geometry, error) { +func SetPoint(lineString geo.Geometry, index int, point geo.Geometry) (geo.Geometry, error) { g, err := lineString.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } lineStringG, ok := g.(*geom.LineString) if !ok { e := geom.ErrUnsupportedType{Value: g} - return nil, errors.Wrap(e, "geometry to be modified must be a LineString") + return geo.Geometry{}, errors.Wrap(e, "geometry to be modified must be a LineString") } g, err = point.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } pointG, ok := g.(*geom.Point) if !ok { e := geom.ErrUnsupportedType{Value: g} - return nil, errors.Wrapf(e, "invalid geometry used to replace a Point on a LineString") + return geo.Geometry{}, errors.Wrapf(e, "invalid geometry used to replace a Point on a LineString") } g, err = setPoint(lineStringG, index, pointG) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func setPoint(lineString *geom.LineString, index int, point *geom.Point) (*geom.LineString, error) { @@ -70,28 +70,28 @@ func setPoint(lineString *geom.LineString, index int, point *geom.Point) (*geom. } // RemovePoint removes the point at the given index of lineString; index is 0-based. -func RemovePoint(lineString *geo.Geometry, index int) (*geo.Geometry, error) { +func RemovePoint(lineString geo.Geometry, index int) (geo.Geometry, error) { g, err := lineString.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } lineStringG, ok := g.(*geom.LineString) if !ok { e := geom.ErrUnsupportedType{Value: g} - return nil, errors.Wrap(e, "geometry to be modified must be a LineString") + return geo.Geometry{}, errors.Wrap(e, "geometry to be modified must be a LineString") } if lineStringG.NumCoords() == 2 { - return nil, errors.Newf("cannot remove a point from a LineString with only two Points") + return geo.Geometry{}, errors.Newf("cannot remove a point from a LineString with only two Points") } g, err = removePoint(lineStringG, index) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func removePoint(lineString *geom.LineString, index int) (*geom.LineString, error) { diff --git a/pkg/geo/geomfn/linestring_test.go b/pkg/geo/geomfn/linestring_test.go index e4dc06b8d86f..a07bbf19d525 100644 --- a/pkg/geo/geomfn/linestring_test.go +++ b/pkg/geo/geomfn/linestring_test.go @@ -54,16 +54,16 @@ func TestSetPoint(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - ls, err := geo.NewGeometryFromGeomT(tc.lineString) + ls, err := geo.MakeGeometryFromGeomT(tc.lineString) require.NoError(t, err) - p, err := geo.NewGeometryFromGeomT(tc.point) + p, err := geo.MakeGeometryFromGeomT(tc.point) require.NoError(t, err) got, err := SetPoint(ls, tc.index, p) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -95,10 +95,10 @@ func TestSetPoint(t *testing.T) { for i, tc := range errTestCases { t.Run(fmt.Sprintf("error-%d", i), func(t *testing.T) { - ls, err := geo.NewGeometryFromGeomT(tc.lineString) + ls, err := geo.MakeGeometryFromGeomT(tc.lineString) require.NoError(t, err) - p, err := geo.NewGeometryFromGeomT(tc.point) + p, err := geo.MakeGeometryFromGeomT(tc.point) require.NoError(t, err) wantErr := fmt.Sprintf("index %d out of range of LineString with %d coordinates", tc.index, tc.lineString.NumCoords()) @@ -133,13 +133,13 @@ func TestRemovePoint(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - ls, err := geo.NewGeometryFromGeomT(tc.lineString) + ls, err := geo.MakeGeometryFromGeomT(tc.lineString) require.NoError(t, err) got, err := RemovePoint(ls, tc.index) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -171,7 +171,7 @@ func TestRemovePoint(t *testing.T) { for i, tc := range errTestCases { t.Run(fmt.Sprintf("error-%d", i), func(t *testing.T) { - ls, err := geo.NewGeometryFromGeomT(tc.lineString) + ls, err := geo.MakeGeometryFromGeomT(tc.lineString) require.NoError(t, err) _, err = RemovePoint(ls, tc.index) diff --git a/pkg/geo/geomfn/make_geometry.go b/pkg/geo/geomfn/make_geometry.go index d077095a00d9..e11551f48f08 100644 --- a/pkg/geo/geomfn/make_geometry.go +++ b/pkg/geo/geomfn/make_geometry.go @@ -18,15 +18,15 @@ import ( // MakePolygon creates a Polygon geometry from linestring and optional inner linestrings. // Returns errors if geometries are not linestrings. -func MakePolygon(outer *geo.Geometry, interior ...*geo.Geometry) (*geo.Geometry, error) { +func MakePolygon(outer geo.Geometry, interior ...geo.Geometry) (geo.Geometry, error) { layout := geom.XY outerGeomT, err := outer.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } outerRing, ok := outerGeomT.(*geom.LineString) if !ok { - return nil, errors.Newf("argument must be LINESTRING geometries") + return geo.Geometry{}, errors.Newf("argument must be LINESTRING geometries") } srid := outerRing.SRID() coords := make([][]geom.Coord, len(interior)+1) @@ -34,21 +34,21 @@ func MakePolygon(outer *geo.Geometry, interior ...*geo.Geometry) (*geo.Geometry, for i, g := range interior { interiorRingGeomT, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } interiorRing, ok := interiorRingGeomT.(*geom.LineString) if !ok { - return nil, errors.Newf("argument must be LINESTRING geometries") + return geo.Geometry{}, errors.Newf("argument must be LINESTRING geometries") } if interiorRing.SRID() != srid { - return nil, errors.Newf("mixed SRIDs are not allowed") + return geo.Geometry{}, errors.Newf("mixed SRIDs are not allowed") } coords[i+1] = interiorRing.Coords() } polygon, err := geom.NewPolygon(layout).SetSRID(srid).SetCoords(coords) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(polygon) + return geo.MakeGeometryFromGeomT(polygon) } diff --git a/pkg/geo/geomfn/make_geometry_test.go b/pkg/geo/geomfn/make_geometry_test.go index b6d996200740..9882f085e049 100644 --- a/pkg/geo/geomfn/make_geometry_test.go +++ b/pkg/geo/geomfn/make_geometry_test.go @@ -238,11 +238,14 @@ func TestMakePolygon(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - outer, err := geo.MustParseGeometry(tc.outer).CloneWithSRID(tc.outerSRID) + outer := geo.MustParseGeometry(tc.outer) + var err error + outer, err = outer.CloneWithSRID(tc.outerSRID) require.NoError(t, err) - interior := make([]*geo.Geometry, 0, len(tc.interior)) + interior := make([]geo.Geometry, 0, len(tc.interior)) for i, g := range tc.interior { - interiorRing, err := geo.MustParseGeometry(g).CloneWithSRID(tc.interiorSRIDs[i]) + interiorRing := geo.MustParseGeometry(g) + interiorRing, err = interiorRing.CloneWithSRID(tc.interiorSRIDs[i]) require.NoError(t, err) interior = append(interior, interiorRing) } @@ -252,7 +255,8 @@ func TestMakePolygon(t *testing.T) { require.EqualError(t, err, tc.err.Error()) } else { require.NoError(t, err) - expected, err := geo.MustParseGeometry(tc.expected).CloneWithSRID(tc.expectedSRID) + expected := geo.MustParseGeometry(tc.expected) + expected, err := expected.CloneWithSRID(tc.expectedSRID) require.NoError(t, err) assert.Equal(t, expected, polygon) } diff --git a/pkg/geo/geomfn/reverse.go b/pkg/geo/geomfn/reverse.go index d52f1123178d..38cd99f01f84 100644 --- a/pkg/geo/geomfn/reverse.go +++ b/pkg/geo/geomfn/reverse.go @@ -16,18 +16,18 @@ import ( ) // Reverse returns a modified geometry by reversing the order of its vertexes -func Reverse(geometry *geo.Geometry) (*geo.Geometry, error) { +func Reverse(geometry geo.Geometry) (geo.Geometry, error) { g, err := geometry.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } g, err = reverse(g) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func reverse(g geom.T) (geom.T, error) { diff --git a/pkg/geo/geomfn/reverse_test.go b/pkg/geo/geomfn/reverse_test.go index c1a9b73eda8c..5e3f9272a709 100644 --- a/pkg/geo/geomfn/reverse_test.go +++ b/pkg/geo/geomfn/reverse_test.go @@ -49,13 +49,13 @@ func TestReverse(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) got, err := Reverse(geometry) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -83,7 +83,7 @@ func TestReverse(t *testing.T) { for i, tc := range collectionTestCases { t.Run(fmt.Sprintf("collection-%d", i), func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) geometry, err = Reverse(geometry) @@ -110,13 +110,13 @@ func TestReverse(t *testing.T) { for i, input := range noChangeTestCases { t.Run(fmt.Sprintf("no-change-%d", i), func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(input) + geometry, err := geo.MakeGeometryFromGeomT(input) require.NoError(t, err) got, err := Reverse(geometry) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(input) + want, err := geo.MakeGeometryFromGeomT(input) require.NoError(t, err) require.Equal(t, want, got) diff --git a/pkg/geo/geomfn/scale.go b/pkg/geo/geomfn/scale.go index d1c85f3135fa..0c25538928af 100644 --- a/pkg/geo/geomfn/scale.go +++ b/pkg/geo/geomfn/scale.go @@ -18,55 +18,55 @@ import ( // Scale returns a modified Geometry whose coordinates are multiplied by the factors. // If there are missing dimensions in factors, the corresponding dimensions are not scaled. -func Scale(geometry *geo.Geometry, factors []float64) (*geo.Geometry, error) { +func Scale(geometry geo.Geometry, factors []float64) (geo.Geometry, error) { if geometry.Empty() { return geometry, nil } g, err := geometry.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } g, err = scale(g, factors, nil) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } // ScaleRelativeToOrigin returns a modified Geometry whose coordinates are multiplied by the factors relative to the origin func ScaleRelativeToOrigin( - geometry *geo.Geometry, factor *geo.Geometry, origin *geo.Geometry, -) (*geo.Geometry, error) { + geometry geo.Geometry, factor geo.Geometry, origin geo.Geometry, +) (geo.Geometry, error) { if geometry.Empty() { return geometry, nil } g, err := geometry.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } factorG, err := factor.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } _, ok := factorG.(*geom.Point) if !ok { - return nil, errors.Newf("the scaling factor must be a Point") + return geo.Geometry{}, errors.Newf("the scaling factor must be a Point") } originG, err := origin.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } _, ok = originG.(*geom.Point) if !ok { - return nil, errors.Newf("the false origin must be a Point") + return geo.Geometry{}, errors.Newf("the false origin must be a Point") } if factorG.Stride() != originG.Stride() { @@ -74,15 +74,15 @@ func ScaleRelativeToOrigin( Got: factorG.Stride(), Want: originG.Stride(), } - return nil, errors.Wrap(err, "number of dimensions for the scaling factor and origin must be equal") + return geo.Geometry{}, errors.Wrap(err, "number of dimensions for the scaling factor and origin must be equal") } g, err = scale(g, factorG.FlatCoords(), originG) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func scale(g geom.T, factors []float64, origin geom.T) (geom.T, error) { diff --git a/pkg/geo/geomfn/scale_test.go b/pkg/geo/geomfn/scale_test.go index 877fc22a7995..8630932f20df 100644 --- a/pkg/geo/geomfn/scale_test.go +++ b/pkg/geo/geomfn/scale_test.go @@ -71,13 +71,13 @@ func TestScale(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) got, err := Scale(geometry, tc.factors) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -126,19 +126,19 @@ func TestScaleRelativeToOrigin(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) - factor, err := geo.NewGeometryFromGeomT(tc.factor) + factor, err := geo.MakeGeometryFromGeomT(tc.factor) require.NoError(t, err) - origin, err := geo.NewGeometryFromGeomT(tc.origin) + origin, err := geo.MakeGeometryFromGeomT(tc.origin) require.NoError(t, err) got, err := ScaleRelativeToOrigin(geometry, factor, origin) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -179,13 +179,13 @@ func TestCollectionScaleRelativeToOrigin(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) - factor, err := geo.NewGeometryFromGeomT(tc.factor) + factor, err := geo.MakeGeometryFromGeomT(tc.factor) require.NoError(t, err) - origin, err := geo.NewGeometryFromGeomT(tc.origin) + origin, err := geo.MakeGeometryFromGeomT(tc.origin) require.NoError(t, err) geometry, err = ScaleRelativeToOrigin(geometry, factor, origin) @@ -228,13 +228,13 @@ func TestInvalidParametersWhenScalingRelativeToOrigin(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) - factor, err := geo.NewGeometryFromGeomT(tc.factor) + factor, err := geo.MakeGeometryFromGeomT(tc.factor) require.NoError(t, err) - origin, err := geo.NewGeometryFromGeomT(tc.origin) + origin, err := geo.MakeGeometryFromGeomT(tc.origin) require.NoError(t, err) _, err = ScaleRelativeToOrigin(geometry, factor, origin) diff --git a/pkg/geo/geomfn/segmentize.go b/pkg/geo/geomfn/segmentize.go index c1afc9fc6678..6062dcc7974a 100644 --- a/pkg/geo/geomfn/segmentize.go +++ b/pkg/geo/geomfn/segmentize.go @@ -25,23 +25,23 @@ import ( // minimum number of new segments with equal length is created, // between given two-points such that each segment has length less // than or equal to given maximum segment length. -func Segmentize(g *geo.Geometry, segmentMaxLength float64) (*geo.Geometry, error) { +func Segmentize(g geo.Geometry, segmentMaxLength float64) (geo.Geometry, error) { geometry, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } switch geometry := geometry.(type) { case *geom.Point, *geom.MultiPoint: return g, nil default: if segmentMaxLength <= 0 { - return nil, errors.Newf("maximum segment length must be positive") + return geo.Geometry{}, errors.Newf("maximum segment length must be positive") } segGeometry, err := geosegmentize.SegmentizeGeom(geometry, segmentMaxLength, segmentizeCoords) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(segGeometry) + return geo.MakeGeometryFromGeomT(segGeometry) } } diff --git a/pkg/geo/geomfn/topology_operations.go b/pkg/geo/geomfn/topology_operations.go index c49b938c122c..59db1820b277 100644 --- a/pkg/geo/geomfn/topology_operations.go +++ b/pkg/geo/geomfn/topology_operations.go @@ -16,80 +16,80 @@ import ( ) // Centroid returns the Centroid of a given Geometry. -func Centroid(g *geo.Geometry) (*geo.Geometry, error) { +func Centroid(g geo.Geometry) (geo.Geometry, error) { centroidEWKB, err := geos.Centroid(g.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(centroidEWKB) } // ClipByRect clips a given Geometry by the given BoundingBox. -func ClipByRect(g *geo.Geometry, b geo.CartesianBoundingBox) (*geo.Geometry, error) { +func ClipByRect(g geo.Geometry, b geo.CartesianBoundingBox) (geo.Geometry, error) { if g.Empty() { return g, nil } clipByRectEWKB, err := geos.ClipByRect(g.EWKB(), b.LoX, b.LoY, b.HiX, b.HiY) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(clipByRectEWKB) } // ConvexHull returns the convex hull of a given Geometry. -func ConvexHull(g *geo.Geometry) (*geo.Geometry, error) { +func ConvexHull(g geo.Geometry) (geo.Geometry, error) { convexHullEWKB, err := geos.ConvexHull(g.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(convexHullEWKB) } // PointOnSurface returns the PointOnSurface of a given Geometry. -func PointOnSurface(g *geo.Geometry) (*geo.Geometry, error) { +func PointOnSurface(g geo.Geometry) (geo.Geometry, error) { pointOnSurfaceEWKB, err := geos.PointOnSurface(g.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(pointOnSurfaceEWKB) } // Intersection returns the geometries of intersection between A and B. -func Intersection(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) { +func Intersection(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) } retEWKB, err := geos.Intersection(a.EWKB(), b.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(retEWKB) } // Union returns the geometries of intersection between A and B. -func Union(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) { +func Union(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) } retEWKB, err := geos.Union(a.EWKB(), b.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(retEWKB) } // SharedPaths Returns a geometry collection containing paths shared by the two input geometries. -func SharedPaths(a *geo.Geometry, b *geo.Geometry) (*geo.Geometry, error) { +func SharedPaths(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) } paths, err := geos.SharedPaths(a.EWKB(), b.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } gm, err := geo.ParseGeometryFromEWKB(paths) if err != nil { - return nil, err + return geo.Geometry{}, err } return gm, nil } diff --git a/pkg/geo/geomfn/topology_operations_test.go b/pkg/geo/geomfn/topology_operations_test.go index 61119f99955d..3ffab7031ac4 100644 --- a/pkg/geo/geomfn/topology_operations_test.go +++ b/pkg/geo/geomfn/topology_operations_test.go @@ -134,9 +134,9 @@ func TestPointOnSurface(t *testing.T) { func TestIntersection(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry - expected *geo.Geometry + a geo.Geometry + b geo.Geometry + expected geo.Geometry }{ {rightRect, rightRect, geo.MustParseGeometry("POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0))")}, {rightRect, rightRectPoint, rightRectPoint}, @@ -159,9 +159,9 @@ func TestIntersection(t *testing.T) { func TestUnion(t *testing.T) { testCases := []struct { - a *geo.Geometry - b *geo.Geometry - expected *geo.Geometry + a geo.Geometry + b geo.Geometry + expected geo.Geometry }{ {rightRect, rightRect, geo.MustParseGeometry("POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0))")}, {rightRect, rightRectPoint, geo.MustParseGeometry("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")}, @@ -185,13 +185,13 @@ func TestUnion(t *testing.T) { func TestSharedPaths(t *testing.T) { type args struct { - a *geo.Geometry - b *geo.Geometry + a geo.Geometry + b geo.Geometry } tests := []struct { name string args args - want *geo.Geometry + want geo.Geometry wantErr error }{ { @@ -220,7 +220,6 @@ func TestSharedPaths(t *testing.T) { a: geo.MustParseGeometry("MULTIPOINT((0 0), (3 2))"), b: geo.MustParseGeometry("MULTIPOINT((0 1), (1 2))"), }, - want: nil, wantErr: errors.New("geos error: IllegalArgumentException: Geometry is not lineal"), }, { diff --git a/pkg/geo/geomfn/translate.go b/pkg/geo/geomfn/translate.go index b8f7fb282dbe..5b3f315bae31 100644 --- a/pkg/geo/geomfn/translate.go +++ b/pkg/geo/geomfn/translate.go @@ -17,18 +17,18 @@ import ( ) // Translate returns a modified Geometry whose coordinates are incremented or decremented by the deltas. -func Translate(geometry *geo.Geometry, deltas []float64) (*geo.Geometry, error) { +func Translate(geometry geo.Geometry, deltas []float64) (geo.Geometry, error) { g, err := geometry.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } g, err = translate(g, deltas) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(g) + return geo.MakeGeometryFromGeomT(g) } func translate(g geom.T, deltas []float64) (geom.T, error) { diff --git a/pkg/geo/geomfn/translate_test.go b/pkg/geo/geomfn/translate_test.go index 85c96e67c12c..fbbb2ddcda90 100644 --- a/pkg/geo/geomfn/translate_test.go +++ b/pkg/geo/geomfn/translate_test.go @@ -72,13 +72,13 @@ func TestTranslate(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) got, err := Translate(geometry, tc.deltas) require.NoError(t, err) - want, err := geo.NewGeometryFromGeomT(tc.expected) + want, err := geo.MakeGeometryFromGeomT(tc.expected) require.NoError(t, err) require.Equal(t, want, got) @@ -118,7 +118,7 @@ func TestTranslateCollection(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - geometry, err := geo.NewGeometryFromGeomT(tc.input) + geometry, err := geo.MakeGeometryFromGeomT(tc.input) require.NoError(t, err) geometry, err = Translate(geometry, tc.deltas) @@ -138,7 +138,7 @@ func TestTranslateCollection(t *testing.T) { func TestTranslateErrorMismatchedDeltas(t *testing.T) { deltas := []float64{1, 1, 1} - geometry, err := geo.NewGeometryFromPointCoords(0, 0) + geometry, err := geo.MakeGeometryFromPointCoords(0, 0) require.NoError(t, err) _, err = Translate(geometry, deltas) diff --git a/pkg/geo/geomfn/unary_operators.go b/pkg/geo/geomfn/unary_operators.go index 4fb278ab42f7..4baef8c7ff5b 100644 --- a/pkg/geo/geomfn/unary_operators.go +++ b/pkg/geo/geomfn/unary_operators.go @@ -21,7 +21,7 @@ import ( // Length returns the length of a given Geometry. // Note only (MULTI)LINESTRING objects have a length. // (MULTI)POLYGON objects should use Perimeter. -func Length(g *geo.Geometry) (float64, error) { +func Length(g geo.Geometry) (float64, error) { geomRepr, err := g.AsGeomT() if err != nil { return 0, err @@ -66,7 +66,7 @@ func lengthFromGeomT(geomRepr geom.T) (float64, error) { // Perimeter returns the perimeter of a given Geometry. // Note only (MULTI)POLYGON objects have a perimeter. // (MULTI)LineString objects should use Length. -func Perimeter(g *geo.Geometry) (float64, error) { +func Perimeter(g geo.Geometry) (float64, error) { geomRepr, err := g.AsGeomT() if err != nil { return 0, err @@ -109,12 +109,12 @@ func perimeterFromGeomT(geomRepr geom.T) (float64, error) { } // Area returns the area of a given Geometry. -func Area(g *geo.Geometry) (float64, error) { +func Area(g geo.Geometry) (float64, error) { return geos.Area(g.EWKB()) } // Dimension returns the topological dimension of a given Geometry. -func Dimension(g *geo.Geometry) (int, error) { +func Dimension(g geo.Geometry) (int, error) { t, err := g.AsGeomT() if err != nil { return 0, err diff --git a/pkg/geo/geomfn/unary_predicates.go b/pkg/geo/geomfn/unary_predicates.go index 83dbb118e046..98da32504898 100644 --- a/pkg/geo/geomfn/unary_predicates.go +++ b/pkg/geo/geomfn/unary_predicates.go @@ -21,7 +21,7 @@ import ( // IsClosed returns whether the given geometry has equal start and end points. // Collections and multi-types must contain all-closed geometries. Empty // geometries are not closed. -func IsClosed(g *geo.Geometry) (bool, error) { +func IsClosed(g geo.Geometry) (bool, error) { t, err := g.AsGeomT() if err != nil { return false, err @@ -76,7 +76,7 @@ func isClosedFromGeomT(t geom.T) (bool, error) { } // IsCollection returns whether the given geometry is of a collection type. -func IsCollection(g *geo.Geometry) (bool, error) { +func IsCollection(g geo.Geometry) (bool, error) { switch g.ShapeType() { case geopb.ShapeType_MultiPoint, geopb.ShapeType_MultiLineString, geopb.ShapeType_MultiPolygon, geopb.ShapeType_GeometryCollection: @@ -87,13 +87,13 @@ func IsCollection(g *geo.Geometry) (bool, error) { } // IsEmpty returns whether the given geometry is empty. -func IsEmpty(g *geo.Geometry) (bool, error) { +func IsEmpty(g geo.Geometry) (bool, error) { return g.Empty(), nil } // IsRing returns whether the given geometry is a ring, i.e. that it is a // simple and closed line. -func IsRing(g *geo.Geometry) (bool, error) { +func IsRing(g geo.Geometry) (bool, error) { // We explicitly check for empty geometries before checking the type, // to follow PostGIS behavior where all empty geometries return false. if g.Empty() { @@ -118,6 +118,6 @@ func IsRing(g *geo.Geometry) (bool, error) { // IsSimple returns whether the given geometry is simple, i.e. that it does not // intersect or lie tangent to itself. -func IsSimple(g *geo.Geometry) (bool, error) { +func IsSimple(g geo.Geometry) (bool, error) { return geos.IsSimple(g.EWKB()) } diff --git a/pkg/geo/geomfn/validity_check.go b/pkg/geo/geomfn/validity_check.go index 8403f2fcfe2c..398a5fbeb70d 100644 --- a/pkg/geo/geomfn/validity_check.go +++ b/pkg/geo/geomfn/validity_check.go @@ -21,11 +21,11 @@ type ValidDetail struct { // Reason is only populated if IsValid = false. Reason string // InvalidLocation is only populated if IsValid = false. - InvalidLocation *geo.Geometry + InvalidLocation geo.Geometry } // IsValid returns whether the given Geometry is valid. -func IsValid(g *geo.Geometry) (bool, error) { +func IsValid(g geo.Geometry) (bool, error) { isValid, err := geos.IsValid(g.EWKB()) if err != nil { return false, err @@ -34,7 +34,7 @@ func IsValid(g *geo.Geometry) (bool, error) { } // IsValidReason returns the reasoning for whether the Geometry is valid or invalid. -func IsValidReason(g *geo.Geometry) (string, error) { +func IsValidReason(g geo.Geometry) (string, error) { reason, err := geos.IsValidReason(g.EWKB()) if err != nil { return "", err @@ -45,12 +45,12 @@ func IsValidReason(g *geo.Geometry) (string, error) { // IsValidDetail returns information about the validity of a Geometry. // It takes in a flag parameter which behaves the same as the GEOS module, where 1 // means that self-intersecting rings forming holes are considered valid. -func IsValidDetail(g *geo.Geometry, flags int) (ValidDetail, error) { +func IsValidDetail(g geo.Geometry, flags int) (ValidDetail, error) { isValid, reason, locEWKB, err := geos.IsValidDetail(g.EWKB(), flags) if err != nil { return ValidDetail{}, err } - var loc *geo.Geometry + var loc geo.Geometry if len(locEWKB) > 0 { loc, err = geo.ParseGeometryFromEWKB(locEWKB) if err != nil { @@ -65,10 +65,10 @@ func IsValidDetail(g *geo.Geometry, flags int) (ValidDetail, error) { } // MakeValid returns a valid form of the given Geometry. -func MakeValid(g *geo.Geometry) (*geo.Geometry, error) { +func MakeValid(g geo.Geometry) (geo.Geometry, error) { validEWKB, err := geos.MakeValid(g.EWKB()) if err != nil { - return nil, err + return geo.Geometry{}, err } return geo.ParseGeometryFromEWKB(validEWKB) } diff --git a/pkg/geo/geotransform/geotransform.go b/pkg/geo/geotransform/geotransform.go index 2ee76cc1d43e..17bf9f56f6c8 100644 --- a/pkg/geo/geotransform/geotransform.go +++ b/pkg/geo/geotransform/geotransform.go @@ -21,22 +21,22 @@ import ( // Transform projects a given Geometry from a given Proj4Text to another Proj4Text. func Transform( - g *geo.Geometry, from geoprojbase.Proj4Text, to geoprojbase.Proj4Text, newSRID geopb.SRID, -) (*geo.Geometry, error) { + g geo.Geometry, from geoprojbase.Proj4Text, to geoprojbase.Proj4Text, newSRID geopb.SRID, +) (geo.Geometry, error) { if from.Equal(to) { return g.CloneWithSRID(newSRID) } t, err := g.AsGeomT() if err != nil { - return nil, err + return geo.Geometry{}, err } newT, err := transform(t, from, to, newSRID) if err != nil { - return nil, err + return geo.Geometry{}, err } - return geo.NewGeometryFromGeomT(newT) + return geo.MakeGeometryFromGeomT(newT) } // transform performs the projection operation on a geom.T object. diff --git a/pkg/geo/parse.go b/pkg/geo/parse.go index 1a60a2d2b0b6..3e2fed8d791e 100644 --- a/pkg/geo/parse.go +++ b/pkg/geo/parse.go @@ -191,15 +191,15 @@ func hasPrefixIgnoreCase(str string, prefix string) bool { // ParseGeometryPointFromGeoHash converts a GeoHash to a Geometry Point // using a Lng/Lat Point representation of the GeoHash. -func ParseGeometryPointFromGeoHash(g string, precision int) (*Geometry, error) { +func ParseGeometryPointFromGeoHash(g string, precision int) (Geometry, error) { box, err := parseGeoHash(g, precision) if err != nil { - return nil, err + return Geometry{}, err } point := box.Center() - geom, gErr := NewGeometryFromPointCoords(point.Lon, point.Lat) + geom, gErr := MakeGeometryFromPointCoords(point.Lon, point.Lat) if gErr != nil { - return nil, gErr + return Geometry{}, gErr } return geom, nil } diff --git a/pkg/geo/parse_test.go b/pkg/geo/parse_test.go index e5bbf11b3328..207b7cee1197 100644 --- a/pkg/geo/parse_test.go +++ b/pkg/geo/parse_test.go @@ -261,12 +261,12 @@ func TestParseEWKT(t *testing.T) { func TestParseGeometry(t *testing.T) { testCases := []struct { str string - expected *Geometry + expected Geometry expectedErr string }{ { "0101000000000000000000F03F000000000000F03F", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -279,7 +279,7 @@ func TestParseGeometry(t *testing.T) { }, { "0101000020E6100000000000000000F03F000000000000F03F", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -292,7 +292,7 @@ func TestParseGeometry(t *testing.T) { }, { "0101000020FFFFFFFF000000000000f03f000000000000f03f", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -305,7 +305,7 @@ func TestParseGeometry(t *testing.T) { }, { "POINT(1.0 1.0)", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -318,7 +318,7 @@ func TestParseGeometry(t *testing.T) { }, { "SRID=4004;POINT(1.0 1.0)", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -331,7 +331,7 @@ func TestParseGeometry(t *testing.T) { }, { "SRid=4004;POINT(1.0 1.0)", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -344,7 +344,7 @@ func TestParseGeometry(t *testing.T) { }, { "\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f", - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -357,7 +357,7 @@ func TestParseGeometry(t *testing.T) { }, { `{ "type": "Point", "coordinates": [1.0, 1.0] }`, - &Geometry{ + Geometry{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeometryType, EWKB: []byte("\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -370,12 +370,12 @@ func TestParseGeometry(t *testing.T) { }, { "invalid", - nil, + Geometry{}, "geos error: ParseException: Unknown type: 'INVALID'", }, { "", - nil, + Geometry{}, "geo: parsing empty string to geo type", }, } @@ -397,13 +397,13 @@ func TestParseGeometry(t *testing.T) { func TestParseGeography(t *testing.T) { testCases := []struct { str string - expected *Geography + expected Geography expectedErr string }{ { // Even forcing an SRID to 0 using EWKB will make it 4326. "0101000000000000000000F03F000000000000F03F", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -421,7 +421,7 @@ func TestParseGeography(t *testing.T) { }, { "0101000020E6100000000000000000F03F000000000000F03F", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -439,7 +439,7 @@ func TestParseGeography(t *testing.T) { }, { "0101000020FFFFFFFF000000000000f03f000000000000f03f", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -457,7 +457,7 @@ func TestParseGeography(t *testing.T) { }, { "0101000020A40F0000000000000000F03F000000000000F03F", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -475,7 +475,7 @@ func TestParseGeography(t *testing.T) { }, { "POINT(1.0 1.0)", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -494,7 +494,7 @@ func TestParseGeography(t *testing.T) { { // Even forcing an SRID to 0 using WKT will make it 4326. "SRID=0;POINT(1.0 1.0)", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -512,7 +512,7 @@ func TestParseGeography(t *testing.T) { }, { "SRID=4004;POINT(1.0 1.0)", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -530,7 +530,7 @@ func TestParseGeography(t *testing.T) { }, { "\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -548,7 +548,7 @@ func TestParseGeography(t *testing.T) { }, { "\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f", - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xA4\x0F\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -566,7 +566,7 @@ func TestParseGeography(t *testing.T) { }, { `{ "type": "Point", "coordinates": [1.0, 1.0] }`, - &Geography{ + Geography{ spatialObject: geopb.SpatialObject{ Type: geopb.SpatialObjectType_GeographyType, EWKB: []byte("\x01\x01\x00\x00\x20\xe6\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\xf0\x3f"), @@ -584,12 +584,12 @@ func TestParseGeography(t *testing.T) { }, { "invalid", - nil, + Geography{}, "geos error: ParseException: Unknown type: 'INVALID'", }, { "", - nil, + Geography{}, "geo: parsing empty string to geo type", }, } diff --git a/pkg/sql/catalog/colinfo/column_type_properties.go b/pkg/sql/catalog/colinfo/column_type_properties.go index 08f09ecd4d03..9ba436c4f11f 100644 --- a/pkg/sql/catalog/colinfo/column_type_properties.go +++ b/pkg/sql/catalog/colinfo/column_type_properties.go @@ -175,7 +175,7 @@ func AdjustValueToColumnType( case types.GeometryFamily: if in, ok := inVal.(*tree.DGeometry); ok { if err := geo.GeospatialTypeFitsColumnMetadata( - in.Geometry, + &in.Geometry, typ.InternalType.GeoMetadata.SRID, typ.InternalType.GeoMetadata.ShapeType, ); err != nil { @@ -185,7 +185,7 @@ func AdjustValueToColumnType( case types.GeographyFamily: if in, ok := inVal.(*tree.DGeography); ok { if err := geo.GeospatialTypeFitsColumnMetadata( - in.Geography, + &in.Geography, typ.InternalType.GeoMetadata.SRID, typ.InternalType.GeoMetadata.ShapeType, ); err != nil { diff --git a/pkg/sql/rowenc/column_type_encoding.go b/pkg/sql/rowenc/column_type_encoding.go index 5336b374b3b2..6defce3cd2e8 100644 --- a/pkg/sql/rowenc/column_type_encoding.go +++ b/pkg/sql/rowenc/column_type_encoding.go @@ -300,7 +300,7 @@ func DecodeTableKey( } return a.NewDBox2D(tree.DBox2D{CartesianBoundingBox: r}), rkey, err case types.GeographyFamily: - g := a.NewDGeography(tree.DGeography{Geography: geo.NewGeographyUnsafe(geopb.SpatialObject{})}) + g := a.NewDGeography(tree.DGeography{Geography: geo.MakeGeographyUnsafe(geopb.SpatialObject{})}) if dir == encoding.Ascending { rkey, err = encoding.DecodeGeoAscending(key, g.Geography.SpatialObjectRef()) } else { @@ -308,7 +308,7 @@ func DecodeTableKey( } return g, rkey, err case types.GeometryFamily: - g := a.NewDGeometry(tree.DGeometry{Geometry: geo.NewGeometryUnsafe(geopb.SpatialObject{})}) + g := a.NewDGeometry(tree.DGeometry{Geometry: geo.MakeGeometryUnsafe(geopb.SpatialObject{})}) if dir == encoding.Ascending { rkey, err = encoding.DecodeGeoAscending(key, g.Geometry.SpatialObjectRef()) } else { @@ -583,14 +583,14 @@ func DecodeUntaggedDatum(a *DatumAlloc, t *types.T, buf []byte) (tree.Datum, []b } return a.NewDBox2D(tree.DBox2D{CartesianBoundingBox: data}), b, nil case types.GeographyFamily: - g := a.NewDGeography(tree.DGeography{Geography: geo.NewGeographyUnsafe(geopb.SpatialObject{})}) + g := a.NewDGeography(tree.DGeography{Geography: geo.MakeGeographyUnsafe(geopb.SpatialObject{})}) b, err := encoding.DecodeUntaggedGeoValue(buf, g.Geography.SpatialObjectRef()) if err != nil { return nil, b, err } return g, b, nil case types.GeometryFamily: - g := a.NewDGeometry(tree.DGeometry{Geometry: geo.NewGeometryUnsafe(geopb.SpatialObject{})}) + g := a.NewDGeometry(tree.DGeometry{Geometry: geo.MakeGeometryUnsafe(geopb.SpatialObject{})}) b, err := encoding.DecodeUntaggedGeoValue(buf, g.Geometry.SpatialObjectRef()) if err != nil { return nil, b, err @@ -897,13 +897,13 @@ func UnmarshalColumnValue(a *DatumAlloc, typ *types.T, value roachpb.Value) (tre if err != nil { return nil, err } - return a.NewDGeography(tree.DGeography{Geography: geo.NewGeographyUnsafe(v)}), nil + return a.NewDGeography(tree.DGeography{Geography: geo.MakeGeographyUnsafe(v)}), nil case types.GeometryFamily: v, err := value.GetGeo() if err != nil { return nil, err } - return a.NewDGeometry(tree.DGeometry{Geometry: geo.NewGeometryUnsafe(v)}), nil + return a.NewDGeometry(tree.DGeometry{Geometry: geo.MakeGeometryUnsafe(v)}), nil case types.TimeFamily: v, err := value.GetInt() if err != nil { diff --git a/pkg/sql/sem/builtins/aggregate_builtins.go b/pkg/sql/sem/builtins/aggregate_builtins.go index 5625fc780526..d3dd96f2ac22 100644 --- a/pkg/sql/sem/builtins/aggregate_builtins.go +++ b/pkg/sql/sem/builtins/aggregate_builtins.go @@ -651,7 +651,7 @@ func (agg *stMakeLineAgg) Result() (tree.Datum, error) { if len(agg.flatCoords) == 0 { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(geom.NewLineStringFlat(agg.layout, agg.flatCoords)) + g, err := geo.MakeGeometryFromGeomT(geom.NewLineStringFlat(agg.layout, agg.flatCoords)) if err != nil { return nil, err } @@ -695,7 +695,7 @@ func (agg *stUnionAgg) Add(_ context.Context, firstArg tree.Datum, otherArgs ... if err != nil { return err } - return geo.NewMismatchingSRIDsError(geomArg.Geometry, c) + return geo.NewMismatchingSRIDsError(&geomArg.Geometry, &c) } var err error // TODO(#geo):We are allocating a slice for the result each time we diff --git a/pkg/sql/sem/builtins/geo_builtins.go b/pkg/sql/sem/builtins/geo_builtins.go index 7ad06daec1ca..3473167e2d90 100644 --- a/pkg/sql/sem/builtins/geo_builtins.go +++ b/pkg/sql/sem/builtins/geo_builtins.go @@ -303,16 +303,16 @@ calculated, the result is transformed back into a Geography with SRID 4326.` // Geography by transforming it to a relevant Geometry SRID and applying the closure, // before retransforming it back into a geopb.DefaultGeographySRID geometry. func performGeographyOperationUsingBestGeomProjection( - g *geo.Geography, f func(*geo.Geometry) (*geo.Geometry, error), -) (*geo.Geography, error) { + g geo.Geography, f func(geo.Geometry) (geo.Geometry, error), +) (geo.Geography, error) { proj, err := geogfn.BestGeomProjection(g.BoundingRect()) if err != nil { - return nil, err + return geo.Geography{}, err } inLatLonGeom, err := g.AsGeometry() if err != nil { - return nil, err + return geo.Geography{}, err } inProjectedGeom, err := geotransform.Transform( @@ -322,12 +322,12 @@ func performGeographyOperationUsingBestGeomProjection( g.SRID(), ) if err != nil { - return nil, err + return geo.Geography{}, err } outProjectedGeom, err := f(inProjectedGeom) if err != nil { - return nil, err + return geo.Geography{}, err } outGeom, err := geotransform.Transform( @@ -337,7 +337,7 @@ func performGeographyOperationUsingBestGeomProjection( geopb.DefaultGeographySRID, ) if err != nil { - return nil, err + return geo.Geography{}, err } return outGeom.AsGeography() } @@ -576,7 +576,7 @@ var geoBuiltins = map[string]builtinDefinition{ Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { outer := args[0].(*tree.DGeometry) interiorArr := tree.MustBeDArray(args[1]) - interior := make([]*geo.Geometry, len(interiorArr.Array)) + interior := make([]geo.Geometry, len(interiorArr.Array)) for i, v := range interiorArr.Array { g, ok := v.(*tree.DGeometry) if !ok { @@ -768,7 +768,7 @@ var geoBuiltins = map[string]builtinDefinition{ Fn: func(_ *tree.EvalContext, args tree.Datums) (tree.Datum, error) { x := float64(*args[0].(*tree.DFloat)) y := float64(*args[1].(*tree.DFloat)) - g, err := geo.NewGeometryFromPointCoords(x, y) + g, err := geo.MakeGeometryFromPointCoords(x, y) if err != nil { return nil, err } @@ -835,7 +835,7 @@ var geoBuiltins = map[string]builtinDefinition{ if err != nil { return nil, err } - ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT(geopb.DefaultGeometrySRID)) + ret, err := geo.MakeGeometryFromGeomT(bbox.ToGeomT(geopb.DefaultGeometrySRID)) if err != nil { return nil, err } @@ -858,7 +858,7 @@ var geoBuiltins = map[string]builtinDefinition{ if err != nil { return nil, err } - ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT(geopb.DefaultGeometrySRID)) + ret, err := geo.MakeGeometryFromGeomT(bbox.ToGeomT(geopb.DefaultGeometrySRID)) if err != nil { return nil, err } @@ -1616,7 +1616,7 @@ Negative azimuth values and values greater than 2π (360 degrees) are supported. return tree.DNull, nil } coord := t.Coord(0) - retG, err := geo.NewGeometryFromGeomT( + retG, err := geo.MakeGeometryFromGeomT( geom.NewPointFlat(geom.XY, []float64{coord.X(), coord.Y()}).SetSRID(t.SRID()), ) if err != nil { @@ -1706,7 +1706,7 @@ Flags shown square brackets after the geometry type have the following meaning: return tree.DNull, nil } coord := t.Coord(t.NumCoords() - 1) - retG, err := geo.NewGeometryFromGeomT( + retG, err := geo.MakeGeometryFromGeomT( geom.NewPointFlat(geom.XY, []float64{coord.X(), coord.Y()}).SetSRID(t.SRID()), ) if err != nil { @@ -1792,7 +1792,7 @@ Flags shown square brackets after the geometry type have the following meaning: ring := t.LinearRing(0) lineString = geom.NewLineStringFlat(t.Layout(), ring.FlatCoords()) } - ret, err := geo.NewGeometryFromGeomT(lineString.SetSRID(t.SRID())) + ret, err := geo.MakeGeometryFromGeomT(lineString.SetSRID(t.SRID())) if err != nil { return nil, err } @@ -1827,7 +1827,7 @@ Flags shown square brackets after the geometry type have the following meaning: } ring := t.LinearRing(n) lineString := geom.NewLineStringFlat(t.Layout(), ring.FlatCoords()).SetSRID(t.SRID()) - ret, err := geo.NewGeometryFromGeomT(lineString) + ret, err := geo.MakeGeometryFromGeomT(lineString) if err != nil { return nil, err } @@ -1861,7 +1861,7 @@ Flags shown square brackets after the geometry type have the following meaning: if n >= t.NumCoords() { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(geom.NewPointFlat(t.Layout(), t.Coord(n)).SetSRID(t.SRID())) + g, err := geo.MakeGeometryFromGeomT(geom.NewPointFlat(t.Layout(), t.Coord(n)).SetSRID(t.SRID())) if err != nil { return nil, err } @@ -1900,7 +1900,7 @@ Flags shown square brackets after the geometry type have the following meaning: if n >= t.NumPoints() { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(t.Point(n).SetSRID(t.SRID())) + g, err := geo.MakeGeometryFromGeomT(t.Point(n).SetSRID(t.SRID())) if err != nil { return nil, err } @@ -1909,7 +1909,7 @@ Flags shown square brackets after the geometry type have the following meaning: if n >= t.NumLineStrings() { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(t.LineString(n).SetSRID(t.SRID())) + g, err := geo.MakeGeometryFromGeomT(t.LineString(n).SetSRID(t.SRID())) if err != nil { return nil, err } @@ -1918,7 +1918,7 @@ Flags shown square brackets after the geometry type have the following meaning: if n >= t.NumPolygons() { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(t.Polygon(n).SetSRID(t.SRID())) + g, err := geo.MakeGeometryFromGeomT(t.Polygon(n).SetSRID(t.SRID())) if err != nil { return nil, err } @@ -1927,7 +1927,7 @@ Flags shown square brackets after the geometry type have the following meaning: if n >= t.NumGeoms() { return tree.DNull, nil } - g, err := geo.NewGeometryFromGeomT(t.Geom(n)) + g, err := geo.MakeGeometryFromGeomT(t.Geom(n)) if err != nil { return nil, err } @@ -3724,7 +3724,7 @@ The calculations are done on a sphere.`, ret, err := performGeographyOperationUsingBestGeomProjection( g.Geography, - func(g *geo.Geometry) (*geo.Geometry, error) { + func(g geo.Geometry) (geo.Geometry, error) { return geomfn.Buffer(g, geomfn.MakeDefaultBufferParams(), float64(distance)) }, ) @@ -3751,7 +3751,7 @@ The calculations are done on a sphere.`, ret, err := performGeographyOperationUsingBestGeomProjection( g.Geography, - func(g *geo.Geometry) (*geo.Geometry, error) { + func(g geo.Geometry) (geo.Geometry, error) { return geomfn.Buffer( g, geomfn.MakeDefaultBufferParams().WithQuadrantSegments(int(quadSegs)), @@ -3786,7 +3786,7 @@ The calculations are done on a sphere.`, ret, err := performGeographyOperationUsingBestGeomProjection( g.Geography, - func(g *geo.Geometry) (*geo.Geometry, error) { + func(g geo.Geometry) (geo.Geometry, error) { return geomfn.Buffer( g, params, @@ -3858,7 +3858,7 @@ Bottom Left.`, geometryOverload2( func(ctx *tree.EvalContext, a *tree.DGeometry, b *tree.DGeometry) (tree.Datum, error) { if a.Geometry.SRID() != b.Geometry.SRID() { - return nil, geo.NewMismatchingSRIDsError(a, b) + return nil, geo.NewMismatchingSRIDsError(&a.Geometry, &b.Geometry) } aGeomT, err := a.AsGeomT() if err != nil { @@ -3973,7 +3973,7 @@ Bottom Left.`, return g, nil } bbox := g.CartesianBoundingBox().Buffer(delta, delta) - ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT(g.SRID())) + ret, err := geo.MakeGeometryFromGeomT(bbox.ToGeomT(g.SRID())) if err != nil { return nil, err } @@ -3999,7 +3999,7 @@ Bottom Left.`, return g, nil } bbox := g.CartesianBoundingBox().Buffer(deltaX, deltaY) - ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT(g.SRID())) + ret, err := geo.MakeGeometryFromGeomT(bbox.ToGeomT(g.SRID())) if err != nil { return nil, err } @@ -4344,7 +4344,7 @@ func geometryOverload1( // geometryOverload1UnaryPredicate hides the boilerplate for builtins // operating on one geometry wrapping a unary predicate. func geometryOverload1UnaryPredicate( - f func(*geo.Geometry) (bool, error), ib infoBuilder, + f func(geo.Geometry) (bool, error), ib infoBuilder, ) tree.Overload { return geometryOverload1( func(_ *tree.EvalContext, g *tree.DGeometry) (tree.Datum, error) { @@ -4386,7 +4386,7 @@ func geometryOverload2( // geometryOverload2BinaryPredicate hides the boilerplate for builtins // operating on two geometries and the overlap wraps a binary predicate. func geometryOverload2BinaryPredicate( - f func(*geo.Geometry, *geo.Geometry) (bool, error), ib infoBuilder, + f func(geo.Geometry, geo.Geometry) (bool, error), ib infoBuilder, ) tree.Overload { return geometryOverload2( func(_ *tree.EvalContext, a *tree.DGeometry, b *tree.DGeometry) (tree.Datum, error) { @@ -4493,7 +4493,7 @@ func geographyOverload2( // geographyOverload2 hides the boilerplate for builtins operating on two geographys // and the overlap wraps a binary predicate. func geographyOverload2BinaryPredicate( - f func(*geo.Geography, *geo.Geography) (bool, error), ib infoBuilder, + f func(geo.Geography, geo.Geography) (bool, error), ib infoBuilder, ) tree.Overload { return geographyOverload2( func(_ *tree.EvalContext, a *tree.DGeography, b *tree.DGeography) (tree.Datum, error) { diff --git a/pkg/sql/sem/tree/casts.go b/pkg/sql/sem/tree/casts.go index f1e864e39e71..3e75d1892fbb 100644 --- a/pkg/sql/sem/tree/casts.go +++ b/pkg/sql/sem/tree/casts.go @@ -730,7 +730,7 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { return ParseDGeography(d.Contents) case *DGeography: if err := geo.GeospatialTypeFitsColumnMetadata( - d.Geography, + &d.Geography, t.InternalType.GeoMetadata.SRID, t.InternalType.GeoMetadata.ShapeType, ); err != nil { @@ -743,7 +743,7 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { return nil, err } if err := geo.GeospatialTypeFitsColumnMetadata( - g, + &g, t.InternalType.GeoMetadata.SRID, t.InternalType.GeoMetadata.ShapeType, ); err != nil { @@ -775,7 +775,7 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { return ParseDGeometry(d.Contents) case *DGeometry: if err := geo.GeospatialTypeFitsColumnMetadata( - d.Geometry, + &d.Geometry, t.InternalType.GeoMetadata.SRID, t.InternalType.GeoMetadata.ShapeType, ); err != nil { @@ -784,7 +784,7 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { return d, nil case *DGeography: if err := geo.GeospatialTypeFitsColumnMetadata( - d.Geography, + &d.Geography, t.InternalType.GeoMetadata.SRID, t.InternalType.GeoMetadata.ShapeType, ); err != nil { @@ -806,7 +806,7 @@ func PerformCast(ctx *EvalContext, d Datum, t *types.T) (Datum, error) { } return &DGeometry{g}, nil case *DBox2D: - g, err := geo.NewGeometryFromGeomT(d.ToGeomT(geopb.DefaultGeometrySRID)) + g, err := geo.MakeGeometryFromGeomT(d.ToGeomT(geopb.DefaultGeometrySRID)) if err != nil { return nil, err } diff --git a/pkg/sql/sem/tree/datum.go b/pkg/sql/sem/tree/datum.go index e7bd91e0e895..9b9589ea49ad 100644 --- a/pkg/sql/sem/tree/datum.go +++ b/pkg/sql/sem/tree/datum.go @@ -2721,11 +2721,11 @@ func (d *DInterval) Size() uintptr { // DGeography is the Geometry Datum. type DGeography struct { - *geo.Geography + geo.Geography } // NewDGeography returns a new Geography Datum. -func NewDGeography(g *geo.Geography) *DGeography { +func NewDGeography(g geo.Geography) *DGeography { return &DGeography{Geography: g} } @@ -2829,11 +2829,11 @@ func (d *DGeography) Size() uintptr { // DGeometry is the Geometry Datum. type DGeometry struct { - *geo.Geometry + geo.Geometry } // NewDGeometry returns a new Geometry Datum. -func NewDGeometry(g *geo.Geometry) *DGeometry { +func NewDGeometry(g geo.Geometry) *DGeometry { return &DGeometry{Geometry: g} } From fc57f393f3c69c81f4820c895c6520bd37a9864f Mon Sep 17 00:00:00 2001 From: Oliver Tan Date: Wed, 26 Aug 2020 11:09:37 -0700 Subject: [PATCH 2/2] geo: use SpatialObject for MismatchingSRIDError Release justification: low risk, high benefit changes to existing functionality Release note: None --- pkg/geo/errors.go | 11 ++++++----- pkg/geo/geogfn/azimuth.go | 2 +- pkg/geo/geogfn/covers.go | 4 ++-- pkg/geo/geogfn/distance.go | 2 +- pkg/geo/geogfn/dwithin.go | 2 +- pkg/geo/geogfn/intersects.go | 2 +- pkg/geo/geomfn/azimuth.go | 2 +- pkg/geo/geomfn/binary_predicates.go | 22 +++++++++++----------- pkg/geo/geomfn/de9im.go | 4 ++-- pkg/geo/geomfn/distance.go | 12 ++++++------ pkg/geo/geomfn/topology_operations.go | 6 +++--- pkg/sql/sem/builtins/aggregate_builtins.go | 2 +- pkg/sql/sem/builtins/geo_builtins.go | 2 +- 13 files changed, 37 insertions(+), 36 deletions(-) diff --git a/pkg/geo/errors.go b/pkg/geo/errors.go index 894ccffb3750..cd05c56ef88b 100644 --- a/pkg/geo/errors.go +++ b/pkg/geo/errors.go @@ -13,18 +13,19 @@ package geo import ( "fmt" + "github.com/cockroachdb/cockroach/pkg/geo/geopb" "github.com/cockroachdb/errors" ) // NewMismatchingSRIDsError returns the error message for SRIDs of GeospatialTypes // a and b being a mismatch. -func NewMismatchingSRIDsError(a GeospatialType, b GeospatialType) error { +func NewMismatchingSRIDsError(a geopb.SpatialObject, b geopb.SpatialObject) error { return errors.Newf( "operation on mixed SRIDs forbidden: (%s, %d) != (%s, %d)", - a.ShapeType(), - a.SRID(), - b.ShapeType(), - b.SRID(), + a.ShapeType, + a.SRID, + b.ShapeType, + b.SRID, ) } diff --git a/pkg/geo/geogfn/azimuth.go b/pkg/geo/geogfn/azimuth.go index 62ac7b5a8a18..6d0c001cf594 100644 --- a/pkg/geo/geogfn/azimuth.go +++ b/pkg/geo/geogfn/azimuth.go @@ -26,7 +26,7 @@ import ( // Returns an error if any of the two Geography items are not points. func Azimuth(a geo.Geography, b geo.Geography) (*float64, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(&a, &b) + return nil, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } aGeomT, err := a.AsGeomT() diff --git a/pkg/geo/geogfn/covers.go b/pkg/geo/geogfn/covers.go index aa7319b72824..724d41588dd1 100644 --- a/pkg/geo/geogfn/covers.go +++ b/pkg/geo/geogfn/covers.go @@ -41,7 +41,7 @@ import ( // ); func Covers(a geo.Geography, b geo.Geography) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return covers(a, b) } @@ -94,7 +94,7 @@ func covers(a geo.Geography, b geo.Geography) (bool, error) { // See Covers for limitations. func CoveredBy(a geo.Geography, b geo.Geography) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return covers(b, a) } diff --git a/pkg/geo/geogfn/distance.go b/pkg/geo/geogfn/distance.go index 3ab34cc93360..08ea973bd853 100644 --- a/pkg/geo/geogfn/distance.go +++ b/pkg/geo/geogfn/distance.go @@ -33,7 +33,7 @@ func Distance( a geo.Geography, b geo.Geography, useSphereOrSpheroid UseSphereOrSpheroid, ) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(&a, &b) + return 0, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } aRegions, err := a.AsS2(geo.EmptyBehaviorError) diff --git a/pkg/geo/geogfn/dwithin.go b/pkg/geo/geogfn/dwithin.go index 2da44dc294bb..9e78add991e2 100644 --- a/pkg/geo/geogfn/dwithin.go +++ b/pkg/geo/geogfn/dwithin.go @@ -28,7 +28,7 @@ func DWithin( exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if distance < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") diff --git a/pkg/geo/geogfn/intersects.go b/pkg/geo/geogfn/intersects.go index fcf7bc3919b1..934faf9224bd 100644 --- a/pkg/geo/geogfn/intersects.go +++ b/pkg/geo/geogfn/intersects.go @@ -25,7 +25,7 @@ func Intersects(a geo.Geography, b geo.Geography) (bool, error) { return false, nil } if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } aRegions, err := a.AsS2(geo.EmptyBehaviorOmit) diff --git a/pkg/geo/geomfn/azimuth.go b/pkg/geo/geomfn/azimuth.go index b1c998555cfe..da99a075ca96 100644 --- a/pkg/geo/geomfn/azimuth.go +++ b/pkg/geo/geomfn/azimuth.go @@ -27,7 +27,7 @@ import ( // Returns an error if any of the two Geometry items are not points. func Azimuth(a geo.Geometry, b geo.Geometry) (*float64, error) { if a.SRID() != b.SRID() { - return nil, geo.NewMismatchingSRIDsError(&a, &b) + return nil, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } aGeomT, err := a.AsGeomT() diff --git a/pkg/geo/geomfn/binary_predicates.go b/pkg/geo/geomfn/binary_predicates.go index dabee8b40b40..81d3f2c08f0a 100644 --- a/pkg/geo/geomfn/binary_predicates.go +++ b/pkg/geo/geomfn/binary_predicates.go @@ -18,7 +18,7 @@ import ( // Covers returns whether geometry A covers geometry B. func Covers(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -29,7 +29,7 @@ func Covers(a geo.Geometry, b geo.Geometry) (bool, error) { // CoveredBy returns whether geometry A is covered by geometry B. func CoveredBy(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !b.CartesianBoundingBox().Covers(a.CartesianBoundingBox()) { return false, nil @@ -40,7 +40,7 @@ func CoveredBy(a geo.Geometry, b geo.Geometry) (bool, error) { // Contains returns whether geometry A contains geometry B. func Contains(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -51,7 +51,7 @@ func Contains(a geo.Geometry, b geo.Geometry) (bool, error) { // ContainsProperly returns whether geometry A properly contains geometry B. func ContainsProperly(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Covers(b.CartesianBoundingBox()) { return false, nil @@ -62,7 +62,7 @@ func ContainsProperly(a geo.Geometry, b geo.Geometry) (bool, error) { // Crosses returns whether geometry A crosses geometry B. func Crosses(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -73,7 +73,7 @@ func Crosses(a geo.Geometry, b geo.Geometry) (bool, error) { // Disjoint returns whether geometry A is disjoint from geometry B. func Disjoint(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return geos.Disjoint(a.EWKB(), b.EWKB()) } @@ -81,7 +81,7 @@ func Disjoint(a geo.Geometry, b geo.Geometry) (bool, error) { // Equals returns whether geometry A equals geometry B. func Equals(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } // Empty items are equal to each other. // Do this check before the BoundingBoxIntersects check, as we would otherwise @@ -98,7 +98,7 @@ func Equals(a geo.Geometry, b geo.Geometry) (bool, error) { // Intersects returns whether geometry A intersects geometry B. func Intersects(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -109,7 +109,7 @@ func Intersects(a geo.Geometry, b geo.Geometry) (bool, error) { // Overlaps returns whether geometry A overlaps geometry B. func Overlaps(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -120,7 +120,7 @@ func Overlaps(a geo.Geometry, b geo.Geometry) (bool, error) { // Touches returns whether geometry A touches geometry B. func Touches(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !a.CartesianBoundingBox().Intersects(b.CartesianBoundingBox()) { return false, nil @@ -131,7 +131,7 @@ func Touches(a geo.Geometry, b geo.Geometry) (bool, error) { // Within returns whether geometry A is within geometry B. func Within(a geo.Geometry, b geo.Geometry) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if !b.CartesianBoundingBox().Covers(a.CartesianBoundingBox()) { return false, nil diff --git a/pkg/geo/geomfn/de9im.go b/pkg/geo/geomfn/de9im.go index 7cb1bd334378..e3aa1d0ad094 100644 --- a/pkg/geo/geomfn/de9im.go +++ b/pkg/geo/geomfn/de9im.go @@ -20,7 +20,7 @@ import ( // Relate returns the DE-9IM relation between A and B. func Relate(a geo.Geometry, b geo.Geometry) (string, error) { if a.SRID() != b.SRID() { - return "", geo.NewMismatchingSRIDsError(&a, &b) + return "", geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return geos.Relate(a.EWKB(), b.EWKB()) } @@ -28,7 +28,7 @@ func Relate(a geo.Geometry, b geo.Geometry) (string, error) { // RelatePattern returns whether the DE-9IM relation between A and B matches. func RelatePattern(a geo.Geometry, b geo.Geometry, pattern string) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return geos.RelatePattern(a.EWKB(), b.EWKB(), pattern) } diff --git a/pkg/geo/geomfn/distance.go b/pkg/geo/geomfn/distance.go index a117cb7bfe9b..83eb127f84b2 100644 --- a/pkg/geo/geomfn/distance.go +++ b/pkg/geo/geomfn/distance.go @@ -37,7 +37,7 @@ const ( // This returns a geo.EmptyGeometryError if either A or B is EMPTY. func MinDistance(a geo.Geometry, b geo.Geometry) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(&a, &b) + return 0, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return minDistanceInternal(a, b, 0, geo.EmptyBehaviorOmit, geo.FnInclusive) } @@ -46,7 +46,7 @@ func MinDistance(a geo.Geometry, b geo.Geometry) (float64, error) { // geometries A and B. func MaxDistance(a geo.Geometry, b geo.Geometry) (float64, error) { if a.SRID() != b.SRID() { - return 0, geo.NewMismatchingSRIDsError(&a, &b) + return 0, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } return maxDistanceInternal(a, b, math.MaxFloat64, geo.EmptyBehaviorOmit, geo.FnInclusive) } @@ -58,7 +58,7 @@ func DWithin( a geo.Geometry, b geo.Geometry, d float64, exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if d < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") @@ -88,7 +88,7 @@ func DFullyWithin( a geo.Geometry, b geo.Geometry, d float64, exclusivity geo.FnExclusivity, ) (bool, error) { if a.SRID() != b.SRID() { - return false, geo.NewMismatchingSRIDsError(&a, &b) + return false, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } if d < 0 { return false, errors.Newf("dwithin distance cannot be less than zero") @@ -114,7 +114,7 @@ func DFullyWithin( // every pair of points comprising geometries A and B. func LongestLineString(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } u := newGeomMaxDistanceUpdater(math.MaxFloat64, geo.FnInclusive) return distanceLineStringInternal(a, b, u, geo.EmptyBehaviorOmit) @@ -124,7 +124,7 @@ func LongestLineString(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { // every pair of points comprising geometries A and B. func ShortestLineString(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } u := newGeomMinDistanceUpdater(0 /*stopAfter */, geo.FnInclusive) return distanceLineStringInternal(a, b, u, geo.EmptyBehaviorOmit) diff --git a/pkg/geo/geomfn/topology_operations.go b/pkg/geo/geomfn/topology_operations.go index 59db1820b277..0ad3fc00fd7d 100644 --- a/pkg/geo/geomfn/topology_operations.go +++ b/pkg/geo/geomfn/topology_operations.go @@ -57,7 +57,7 @@ func PointOnSurface(g geo.Geometry) (geo.Geometry, error) { // Intersection returns the geometries of intersection between A and B. func Intersection(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } retEWKB, err := geos.Intersection(a.EWKB(), b.EWKB()) if err != nil { @@ -69,7 +69,7 @@ func Intersection(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { // Union returns the geometries of intersection between A and B. func Union(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } retEWKB, err := geos.Union(a.EWKB(), b.EWKB()) if err != nil { @@ -81,7 +81,7 @@ func Union(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { // SharedPaths Returns a geometry collection containing paths shared by the two input geometries. func SharedPaths(a geo.Geometry, b geo.Geometry) (geo.Geometry, error) { if a.SRID() != b.SRID() { - return geo.Geometry{}, geo.NewMismatchingSRIDsError(&a, &b) + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) } paths, err := geos.SharedPaths(a.EWKB(), b.EWKB()) if err != nil { diff --git a/pkg/sql/sem/builtins/aggregate_builtins.go b/pkg/sql/sem/builtins/aggregate_builtins.go index d3dd96f2ac22..c6a3c8ce3585 100644 --- a/pkg/sql/sem/builtins/aggregate_builtins.go +++ b/pkg/sql/sem/builtins/aggregate_builtins.go @@ -695,7 +695,7 @@ func (agg *stUnionAgg) Add(_ context.Context, firstArg tree.Datum, otherArgs ... if err != nil { return err } - return geo.NewMismatchingSRIDsError(&geomArg.Geometry, &c) + return geo.NewMismatchingSRIDsError(geomArg.Geometry.SpatialObject(), c.SpatialObject()) } var err error // TODO(#geo):We are allocating a slice for the result each time we diff --git a/pkg/sql/sem/builtins/geo_builtins.go b/pkg/sql/sem/builtins/geo_builtins.go index 3473167e2d90..05295a19075e 100644 --- a/pkg/sql/sem/builtins/geo_builtins.go +++ b/pkg/sql/sem/builtins/geo_builtins.go @@ -3858,7 +3858,7 @@ Bottom Left.`, geometryOverload2( func(ctx *tree.EvalContext, a *tree.DGeometry, b *tree.DGeometry) (tree.Datum, error) { if a.Geometry.SRID() != b.Geometry.SRID() { - return nil, geo.NewMismatchingSRIDsError(&a.Geometry, &b.Geometry) + return nil, geo.NewMismatchingSRIDsError(a.Geometry.SpatialObject(), b.Geometry.SpatialObject()) } aGeomT, err := a.AsGeomT() if err != nil {