github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/json/json_remove_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 json 16 17 import ( 18 "fmt" 19 "strings" 20 "testing" 21 22 "github.com/stretchr/testify/require" 23 "gopkg.in/src-d/go-errors.v1" 24 25 "github.com/dolthub/go-mysql-server/sql" 26 "github.com/dolthub/go-mysql-server/sql/types" 27 ) 28 29 func TestRemove(t *testing.T) { 30 _, err := NewJSONRemove() 31 require.True(t, errors.Is(err, sql.ErrInvalidArgumentNumber)) 32 33 f1 := buildGetFieldExpressions(t, NewJSONRemove, 2) 34 35 f2 := buildGetFieldExpressions(t, NewJSONRemove, 3) 36 37 json := `{"a": 1, "b": [2, 3], "c": {"d": "foo"}}` 38 39 testCases := []struct { 40 f sql.Expression 41 row sql.Row 42 expected interface{} 43 err error 44 }{ 45 {f1, sql.Row{json, "$.a"}, `{"b": [2, 3], "c": {"d": "foo"}}`, nil}, // remove existing 46 {f1, sql.Row{json, "$.b[0]"}, `{"a": 1, "b": [3], "c": {"d": "foo"}}`, nil}, // remove existing array element 47 {f1, sql.Row{json, "$.c.d"}, `{"a": 1, "b": [2, 3], "c": {}}`, nil}, // remove existing nested 48 {f1, sql.Row{json, "$.c"}, `{"a": 1, "b": [2, 3]}`, nil}, // remove existing object 49 {f1, sql.Row{json, "$.a.e"}, json, nil}, // remove nothing when path not found 50 {f1, sql.Row{json, "$.c[5]"}, json, nil}, // remove nothing when path not found 51 {f1, sql.Row{json, "$.b[last]"}, `{"a": 1, "b": [2], "c": {"d": "foo"}}`, nil}, // remove last element in array 52 {f1, sql.Row{json, "$.b[5]"}, json, nil}, // remove nothing when array index out of bounds 53 {f1, sql.Row{json, "$[0]"}, json, nil}, // remove nothing when provided a bogus path. 54 {f1, sql.Row{json, "$.[0]"}, nil, ErrInvalidPath}, // improper struct indexing 55 {f1, sql.Row{json, "foo", "test"}, nil, ErrInvalidPath}, // invalid path 56 {f1, sql.Row{json, "$.c.*", "test"}, nil, ErrPathWildcard}, // path contains * wildcard 57 {f1, sql.Row{json, "$.c.**", "test"}, nil, ErrPathWildcard}, // path contains ** wildcard 58 {f1, sql.Row{json, "$"}, nil, fmt.Errorf("The path expression '$' is not allowed in this context.")}, // whole document 59 {f1, sql.Row{nil, "$"}, nil, nil}, // null document 60 {f2, sql.Row{json, "$.foo", nil}, nil, nil}, // if any path is null, return null 61 {f2, sql.Row{json, "$.a", "$.b"}, `{"c": {"d": "foo"}}`, nil}, // remove multiple paths 62 } 63 64 for _, tstC := range testCases { 65 var paths []string 66 for _, path := range tstC.row[1:] { 67 if _, ok := path.(string); ok { 68 paths = append(paths, path.(string)) 69 } 70 } 71 72 t.Run(tstC.f.String()+"."+strings.Join(paths, ","), func(t *testing.T) { 73 req := require.New(t) 74 result, err := tstC.f.Eval(sql.NewEmptyContext(), tstC.row) 75 if tstC.err == nil { 76 req.NoError(err) 77 78 var expect interface{} 79 if tstC.expected != nil { 80 expect, _, err = types.JSON.Convert(tstC.expected) 81 if err != nil { 82 panic("Bad test string. Can't convert string to JSONDocument: " + tstC.expected.(string)) 83 } 84 } 85 86 req.Equal(expect, result) 87 } else { 88 req.Error(tstC.err, err) 89 } 90 }) 91 } 92 }