github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/spatial/st_area_test.go (about) 1 // Copyright 2020-2022 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 TestArea(t *testing.T) { 28 t.Run("select area of right triangle", func(t *testing.T) { 29 require := require.New(t) 30 polygon := types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}} 31 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 32 v, err := f.Eval(sql.NewEmptyContext(), nil) 33 require.NoError(err) 34 require.Equal(0.5, v) 35 }) 36 37 t.Run("select area of unit square", func(t *testing.T) { 38 require := require.New(t) 39 polygon := types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 1, Y: 0}, {X: 0, Y: 0}}}}} 40 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 41 v, err := f.Eval(sql.NewEmptyContext(), nil) 42 require.NoError(err) 43 require.Equal(1.0, v) 44 }) 45 46 t.Run("select area of some shape", func(t *testing.T) { 47 require := require.New(t) 48 polygon := types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3.2, Y: 4.5}, {X: -12.2, Y: 23}, {X: 55, Y: 88}, {X: 33, Y: 255.123}, {X: 17, Y: 2}, {X: 1, Y: 2}}}}} 49 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 50 v, err := f.Eval(sql.NewEmptyContext(), nil) 51 require.NoError(err) 52 require.Equal(2338.337, v) // we round 53 }) 54 55 t.Run("select area of right triangle with a hole", func(t *testing.T) { 56 require := require.New(t) 57 line1 := types.LineString{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 3}, {X: 3, Y: 0}, {X: 0, Y: 0}}} 58 line2 := types.LineString{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: 2}, {X: 2, Y: 1}, {X: 1, Y: 1}}} 59 polygon := types.Polygon{Lines: []types.LineString{line1, line2}} 60 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 61 v, err := f.Eval(sql.NewEmptyContext(), nil) 62 require.NoError(err) 63 require.Equal(4.0, v) 64 }) 65 66 t.Run("select area of right triangle with many holes", func(t *testing.T) { 67 require := require.New(t) 68 line1 := types.LineString{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 3}, {X: 3, Y: 0}, {X: 0, Y: 0}}} 69 line2 := types.LineString{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: 2}, {X: 2, Y: 1}, {X: 1, Y: 1}}} 70 polygon := types.Polygon{Lines: []types.LineString{line1, line2, line2, line2}} 71 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 72 v, err := f.Eval(sql.NewEmptyContext(), nil) 73 require.NoError(err) 74 require.Equal(3.0, v) 75 }) 76 77 t.Run("select area of right triangle hole", func(t *testing.T) { 78 require := require.New(t) 79 line1 := types.LineString{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 3}, {X: 3, Y: 0}, {X: 0, Y: 0}}} 80 polygon := types.Polygon{Lines: []types.LineString{line1, line1}} 81 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 82 v, err := f.Eval(sql.NewEmptyContext(), nil) 83 require.NoError(err) 84 require.Equal(0.0, v) 85 }) 86 87 t.Run("select area of polygon that intersects itself", func(t *testing.T) { 88 require := require.New(t) 89 line := types.LineString{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: -10, Y: 10}, {X: 10, Y: 10}, {X: 0, Y: 0}}} 90 polygon := types.Polygon{Lines: []types.LineString{line}} 91 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 92 v, err := f.Eval(sql.NewEmptyContext(), nil) 93 require.NoError(err) 94 require.Equal(95.0, v) 95 }) 96 97 t.Run("select area of NULL", func(t *testing.T) { 98 require := require.New(t) 99 f := NewArea(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("select area of wrong type", func(t *testing.T) { 106 require := require.New(t) 107 f := NewArea(expression.NewLiteral("abc", types.Text)) 108 v, err := f.Eval(sql.NewEmptyContext(), nil) 109 require.Error(err) 110 require.Equal(nil, v) 111 }) 112 113 // TODO: this should eventually work 114 t.Run("block non-cartesian SRID", func(t *testing.T) { 115 require := require.New(t) 116 polygon := types.Polygon{SRID: 3857, Lines: []types.LineString{{SRID: 3857, Points: []types.Point{{SRID: 3857, X: 0, Y: 0}, {SRID: 3857, X: 0, Y: 1}, {SRID: 3857, X: 1, Y: 1}, {SRID: 3857, X: 0, Y: 0}}}}} 117 f := NewArea(expression.NewLiteral(polygon, types.PolygonType{})) 118 _, err := f.Eval(sql.NewEmptyContext(), nil) 119 require.Error(err) 120 }) 121 122 }