github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/spatial/st_equals.go (about) 1 // Copyright 2023 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package spatial 16 17 import ( 18 "fmt" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 "github.com/dolthub/go-mysql-server/sql/expression" 22 "github.com/dolthub/go-mysql-server/sql/types" 23 ) 24 25 // STEquals is a function that returns the STEquals of a LineString 26 type STEquals struct { 27 expression.BinaryExpressionStub 28 } 29 30 var _ sql.FunctionExpression = (*STEquals)(nil) 31 32 // NewSTEquals creates a new STEquals expression. 33 func NewSTEquals(g1, g2 sql.Expression) sql.Expression { 34 return &STEquals{ 35 expression.BinaryExpressionStub{ 36 LeftChild: g1, 37 RightChild: g2, 38 }, 39 } 40 } 41 42 // FunctionName implements sql.FunctionExpression 43 func (s *STEquals) FunctionName() string { 44 return "st_equals" 45 } 46 47 // Description implements sql.FunctionExpression 48 func (s *STEquals) Description() string { 49 return "returns 1 or 0 to indicate whether g1 is spatially equal to g2." 50 } 51 52 // Type implements the sql.Expression interface. 53 func (s *STEquals) Type() sql.Type { 54 return types.Boolean 55 } 56 57 func (s *STEquals) String() string { 58 return fmt.Sprintf("ST_EQUALS(%s, %s)", s.LeftChild, s.RightChild) 59 } 60 61 // WithChildren implements the Expression interface. 62 func (s *STEquals) WithChildren(children ...sql.Expression) (sql.Expression, error) { 63 if len(children) != 2 { 64 return nil, sql.ErrInvalidChildrenNumber.New(s, len(children), 2) 65 } 66 return NewSTEquals(children[0], children[1]), nil 67 } 68 69 // isEqual checks if the set of types.Points in g1 is spatially equal to g2 70 // This is equivalent to checking if g1 within g2 and g2 within g1 71 func isEqual(g1 types.GeometryValue, g2 types.GeometryValue) bool { 72 return isWithin(g1, g2) && isWithin(g2, g1) 73 } 74 75 // Eval implements the sql.Expression interface. 76 func (s *STEquals) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 77 geom1, err := s.LeftChild.Eval(ctx, row) 78 if err != nil { 79 return nil, err 80 } 81 geom2, err := s.RightChild.Eval(ctx, row) 82 if err != nil { 83 return nil, err 84 } 85 g1, g2, err := validateGeomComp(geom1, geom2, s.FunctionName()) 86 if err != nil { 87 return nil, err 88 } 89 if g1 == nil || g2 == nil { 90 return nil, nil 91 } 92 93 // TODO (james): remove this switch block when the other comparisons are implemented 94 switch geom1.(type) { 95 case types.LineString: 96 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("LineString", s.FunctionName()) 97 case types.Polygon: 98 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("Polygon", s.FunctionName()) 99 case types.MultiPoint: 100 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiPoint", s.FunctionName()) 101 case types.MultiLineString: 102 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiLineString", s.FunctionName()) 103 case types.MultiPolygon: 104 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiPolygon", s.FunctionName()) 105 case types.GeomColl: 106 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("GeomColl", s.FunctionName()) 107 } 108 109 // TODO (james): remove this switch block when the other comparisons are implemented 110 switch geom2.(type) { 111 case types.LineString: 112 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("LineString", s.FunctionName()) 113 case types.Polygon: 114 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("Polygon", s.FunctionName()) 115 case types.MultiPoint: 116 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiPoint", s.FunctionName()) 117 case types.MultiLineString: 118 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiLineString", s.FunctionName()) 119 case types.MultiPolygon: 120 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("MultiPolygon", s.FunctionName()) 121 case types.GeomColl: 122 return nil, sql.ErrUnsupportedGISTypeForSpatialFunc.New("GeomColl", s.FunctionName()) 123 } 124 125 return isEqual(g1, g2), nil 126 }