github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/spatial/st_linestring_test.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 "testing" 19 20 "github.com/stretchr/testify/require" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/expression" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 func TestStartPoint(t *testing.T) { 28 t.Run("simple case", func(t *testing.T) { 29 require := require.New(t) 30 s := types.Point{X: 123, Y: 456} 31 e := types.Point{X: 456, Y: 789} 32 l := types.LineString{Points: []types.Point{s, e}} 33 f := NewStartPoint(expression.NewLiteral(l, types.LineStringType{})) 34 v, err := f.Eval(sql.NewEmptyContext(), nil) 35 require.NoError(err) 36 require.Equal(s, v) 37 }) 38 39 t.Run("simple case with SRID", func(t *testing.T) { 40 require := require.New(t) 41 s := types.Point{SRID: types.GeoSpatialSRID, X: 123, Y: 456} 42 e := types.Point{SRID: types.GeoSpatialSRID, X: 456, Y: 789} 43 l := types.LineString{Points: []types.Point{s, e}} 44 f := NewStartPoint(expression.NewLiteral(l, types.LineStringType{})) 45 v, err := f.Eval(sql.NewEmptyContext(), nil) 46 require.NoError(err) 47 require.Equal(s, v) 48 }) 49 50 t.Run("null argument", func(t *testing.T) { 51 require := require.New(t) 52 f := NewStartPoint(expression.NewLiteral(nil, types.Null)) 53 v, err := f.Eval(sql.NewEmptyContext(), nil) 54 require.NoError(err) 55 require.Equal(nil, v) 56 }) 57 58 t.Run("non-linestring argument", func(t *testing.T) { 59 require := require.New(t) 60 f := NewStartPoint(expression.NewLiteral(types.Point{SRID: types.GeoSpatialSRID, X: 123, Y: 456}, types.Null)) 61 v, err := f.Eval(sql.NewEmptyContext(), nil) 62 require.NoError(err) 63 require.Equal(nil, v) 64 }) 65 66 t.Run("non-geometry argument", func(t *testing.T) { 67 require := require.New(t) 68 f := NewStartPoint(expression.NewLiteral(123, types.Int8)) 69 _, err := f.Eval(sql.NewEmptyContext(), nil) 70 require.Error(err) 71 }) 72 } 73 74 func TestEndPoint(t *testing.T) { 75 t.Run("simple case", func(t *testing.T) { 76 require := require.New(t) 77 s := types.Point{X: 123, Y: 456} 78 e := types.Point{X: 456, Y: 789} 79 l := types.LineString{Points: []types.Point{s, e}} 80 f := NewEndPoint(expression.NewLiteral(l, types.LineStringType{})) 81 v, err := f.Eval(sql.NewEmptyContext(), nil) 82 require.NoError(err) 83 require.Equal(e, v) 84 }) 85 86 t.Run("simple case with SRID", func(t *testing.T) { 87 require := require.New(t) 88 s := types.Point{SRID: types.GeoSpatialSRID, X: 123, Y: 456} 89 e := types.Point{SRID: types.GeoSpatialSRID, X: 456, Y: 789} 90 l := types.LineString{Points: []types.Point{s, e}} 91 f := NewEndPoint(expression.NewLiteral(l, types.LineStringType{})) 92 v, err := f.Eval(sql.NewEmptyContext(), nil) 93 require.NoError(err) 94 require.Equal(e, v) 95 }) 96 97 t.Run("null argument", func(t *testing.T) { 98 require := require.New(t) 99 f := NewEndPoint(expression.NewLiteral(nil, types.Null)) 100 v, err := f.Eval(sql.NewEmptyContext(), nil) 101 require.NoError(err) 102 require.Equal(nil, v) 103 }) 104 105 t.Run("non-linestring argument", func(t *testing.T) { 106 require := require.New(t) 107 f := NewEndPoint(expression.NewLiteral(types.Point{SRID: types.GeoSpatialSRID, X: 123, Y: 456}, types.Null)) 108 v, err := f.Eval(sql.NewEmptyContext(), nil) 109 require.NoError(err) 110 require.Equal(nil, v) 111 }) 112 113 t.Run("non-geometry argument", func(t *testing.T) { 114 require := require.New(t) 115 f := NewEndPoint(expression.NewLiteral(123, types.Int8)) 116 _, err := f.Eval(sql.NewEmptyContext(), nil) 117 require.Error(err) 118 }) 119 } 120 121 func TestIsClosed(t *testing.T) { 122 t.Run("simple case is closed", func(t *testing.T) { 123 require := require.New(t) 124 s := types.Point{X: 0, Y: 0} 125 p1 := types.Point{X: 1, Y: 1} 126 p2 := types.Point{X: 2, Y: 2} 127 p3 := types.Point{X: 3, Y: 3} 128 l := types.LineString{Points: []types.Point{s, p1, p2, p3, s}} 129 f := NewIsClosed(expression.NewLiteral(l, types.LineStringType{})) 130 v, err := f.Eval(sql.NewEmptyContext(), nil) 131 require.NoError(err) 132 require.Equal(true, v) 133 }) 134 135 t.Run("simple case with SRID is closed", func(t *testing.T) { 136 require := require.New(t) 137 s := types.Point{SRID: types.GeoSpatialSRID, X: 0, Y: 0} 138 p1 := types.Point{SRID: types.GeoSpatialSRID, X: 1, Y: 1} 139 p2 := types.Point{SRID: types.GeoSpatialSRID, X: 2, Y: 2} 140 p3 := types.Point{SRID: types.GeoSpatialSRID, X: 3, Y: 3} 141 l := types.LineString{Points: []types.Point{s, p1, p2, p3, s}} 142 f := NewIsClosed(expression.NewLiteral(l, types.LineStringType{})) 143 v, err := f.Eval(sql.NewEmptyContext(), nil) 144 require.NoError(err) 145 require.Equal(true, v) 146 }) 147 148 t.Run("simple case is not closed", func(t *testing.T) { 149 require := require.New(t) 150 s := types.Point{X: 0, Y: 0} 151 p1 := types.Point{X: 1, Y: 1} 152 p2 := types.Point{X: 2, Y: 2} 153 p3 := types.Point{X: 3, Y: 3} 154 l := types.LineString{Points: []types.Point{s, p1, p2, p3}} 155 f := NewIsClosed(expression.NewLiteral(l, types.LineStringType{})) 156 v, err := f.Eval(sql.NewEmptyContext(), nil) 157 require.NoError(err) 158 require.Equal(false, v) 159 }) 160 161 t.Run("multilinestring all closed", func(t *testing.T) { 162 require := require.New(t) 163 s := types.Point{X: 0, Y: 0} 164 p1 := types.Point{X: 1, Y: 1} 165 p2 := types.Point{X: 2, Y: 2} 166 p3 := types.Point{X: 3, Y: 3} 167 l1 := types.LineString{Points: []types.Point{s, p1, p2, p3, s}} 168 l2 := types.LineString{Points: []types.Point{s, p2, p1, s}} 169 ml := types.MultiLineString{Lines: []types.LineString{l1, l2}} 170 f := NewIsClosed(expression.NewLiteral(ml, types.MultiLineStringType{})) 171 v, err := f.Eval(sql.NewEmptyContext(), nil) 172 require.NoError(err) 173 require.Equal(true, v) 174 }) 175 176 t.Run("multilinestring one line not closed", func(t *testing.T) { 177 require := require.New(t) 178 s := types.Point{X: 0, Y: 0} 179 p1 := types.Point{X: 1, Y: 1} 180 p2 := types.Point{X: 2, Y: 2} 181 p3 := types.Point{X: 3, Y: 3} 182 l1 := types.LineString{Points: []types.Point{s, p1, p2, p3, s}} 183 l2 := types.LineString{Points: []types.Point{s, p2, p1}} 184 ml := types.MultiLineString{Lines: []types.LineString{l1, l2}} 185 f := NewIsClosed(expression.NewLiteral(ml, types.MultiLineStringType{})) 186 v, err := f.Eval(sql.NewEmptyContext(), nil) 187 require.NoError(err) 188 require.Equal(false, v) 189 }) 190 191 t.Run("zero length linestring is closed", func(t *testing.T) { 192 require := require.New(t) 193 s := types.Point{X: 0, Y: 0} 194 l := types.LineString{Points: []types.Point{s, s, s}} 195 f := NewIsClosed(expression.NewLiteral(l, types.LineStringType{})) 196 v, err := f.Eval(sql.NewEmptyContext(), nil) 197 require.NoError(err) 198 require.Equal(true, v) 199 }) 200 201 t.Run("null argument", func(t *testing.T) { 202 require := require.New(t) 203 f := NewIsClosed(expression.NewLiteral(nil, types.Null)) 204 v, err := f.Eval(sql.NewEmptyContext(), nil) 205 require.NoError(err) 206 require.Equal(nil, v) 207 }) 208 209 t.Run("non-linestring argument", func(t *testing.T) { 210 require := require.New(t) 211 f := NewIsClosed(expression.NewLiteral(types.Point{SRID: types.GeoSpatialSRID, X: 123, Y: 456}, types.Null)) 212 v, err := f.Eval(sql.NewEmptyContext(), nil) 213 require.NoError(err) 214 require.Equal(nil, v) 215 }) 216 217 t.Run("non-geometry argument", func(t *testing.T) { 218 require := require.New(t) 219 f := NewIsClosed(expression.NewLiteral(123, types.Int8)) 220 _, err := f.Eval(sql.NewEmptyContext(), nil) 221 require.Error(err) 222 }) 223 }