github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/spatial/st_srid.go (about) 1 // Copyright 2020-2021 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 "strings" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/dolthub/go-mysql-server/sql/expression" 23 "github.com/dolthub/go-mysql-server/sql/types" 24 ) 25 26 // SRID is a function that returns SRID of Geometry object or returns a new object with altered SRID. 27 type SRID struct { 28 expression.NaryExpression 29 } 30 31 var _ sql.FunctionExpression = (*SRID)(nil) 32 var _ sql.CollationCoercible = (*SRID)(nil) 33 34 // NewSRID creates a new STX expression. 35 func NewSRID(args ...sql.Expression) (sql.Expression, error) { 36 if len(args) != 1 && len(args) != 2 { 37 return nil, sql.ErrInvalidArgumentNumber.New("ST_SRID", "1 or 2", len(args)) 38 } 39 return &SRID{expression.NaryExpression{ChildExpressions: args}}, nil 40 } 41 42 // FunctionName implements sql.FunctionExpression 43 func (s *SRID) FunctionName() string { 44 return "st_srid" 45 } 46 47 // Description implements sql.FunctionExpression 48 func (s *SRID) Description() string { 49 return "returns the SRID value of given geometry object. If given a second argument, returns a new geometry object with second argument as SRID value." 50 } 51 52 // Type implements the sql.Expression interface. 53 func (s *SRID) Type() sql.Type { 54 if len(s.ChildExpressions) == 1 { 55 return types.Int32 56 } else { 57 return s.ChildExpressions[0].Type() 58 } 59 } 60 61 // CollationCoercibility implements the interface sql.CollationCoercible. 62 func (*SRID) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 63 return sql.Collation_binary, 5 64 } 65 66 func (s *SRID) String() string { 67 var args = make([]string, len(s.ChildExpressions)) 68 for i, arg := range s.ChildExpressions { 69 args[i] = arg.String() 70 } 71 return fmt.Sprintf("ST_SRID(%s)", strings.Join(args, ",")) 72 } 73 74 // WithChildren implements the Expression interface. 75 func (s *SRID) WithChildren(children ...sql.Expression) (sql.Expression, error) { 76 return NewSRID(children...) 77 } 78 79 // Eval implements the sql.Expression interface. 80 func (s *SRID) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 81 g, err := s.ChildExpressions[0].Eval(ctx, row) 82 if err != nil { 83 return nil, err 84 } 85 86 if g == nil { 87 return nil, nil 88 } 89 90 // If just one argument, return SRID 91 if len(s.ChildExpressions) == 1 { 92 switch g := g.(type) { 93 case types.GeometryValue: 94 return g.GetSRID(), nil 95 default: 96 return nil, sql.ErrIllegalGISValue.New(g) 97 } 98 } 99 100 v, err := s.ChildExpressions[1].Eval(ctx, row) 101 if err != nil { 102 return nil, err 103 } 104 105 if v == nil { 106 return nil, nil 107 } 108 109 val, _, err := types.Int64.Convert(v) 110 if err != nil { 111 return nil, err 112 } 113 114 if err = types.ValidateSRID(int(val.(int64)), s.FunctionName()); err != nil { 115 return nil, err 116 } 117 srid := uint32(val.(int64)) 118 119 // Create new geometry object with matching SRID 120 switch g := g.(type) { 121 case types.GeometryValue: 122 return g.SetSRID(srid), nil 123 default: 124 return nil, sql.ErrIllegalGISValue.New(g) 125 } 126 }