github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/json/json_array_append_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 "strings" 19 "testing" 20 21 "github.com/stretchr/testify/require" 22 "gopkg.in/src-d/go-errors.v1" 23 24 "github.com/dolthub/go-mysql-server/sql" 25 "github.com/dolthub/go-mysql-server/sql/types" 26 ) 27 28 func TestArrayAppend(t *testing.T) { 29 _, err := NewJSONArrayInsert() 30 require.True(t, errors.Is(err, sql.ErrInvalidArgumentNumber)) 31 32 f1 := buildGetFieldExpressions(t, NewJSONArrayAppend, 3) 33 f2 := buildGetFieldExpressions(t, NewJSONArrayAppend, 5) 34 35 json := `{"a": 1, "b": [2, 3], "c": {"d": "foo"}}` 36 37 testCases := []struct { 38 f sql.Expression 39 row sql.Row 40 expected interface{} 41 err error 42 }{ 43 44 {f1, sql.Row{json, "$.b[0]", 4.1}, `{"a": 1, "b": [[2,4.1], 3], "c": {"d": "foo"}}`, nil}, 45 {f1, sql.Row{json, "$.a", 4.1}, `{"a": [1, 4.1], "b": [2, 3], "c": {"d": "foo"}}`, nil}, 46 {f1, sql.Row{json, "$.e", "new"}, json, nil}, 47 {f1, sql.Row{json, "$.c.d", "test"}, `{"a": 1, "b": [2, 3], "c": {"d": ["foo", "test"]}}`, nil}, 48 {f2, sql.Row{json, "$.b[0]", 4.1, "$.c.d", "test"}, `{"a": 1, "b": [[2, 4.1], 3], "c": {"d": ["foo", "test"]}}`, nil}, 49 {f1, sql.Row{json, "$.b[5]", 4.1}, json, nil}, 50 {f1, sql.Row{json, "$.b.c", 4}, json, nil}, 51 {f1, sql.Row{json, "$.a[51]", 4.1}, json, nil}, 52 {f1, sql.Row{json, "$.a[last-1]", 4.1}, json, nil}, 53 {f1, sql.Row{json, "$.a[0]", 4.1}, `{"a": [1, 4.1], "b": [2, 3], "c": {"d": "foo"}}`, nil}, 54 {f1, sql.Row{json, "$.a[last]", 4.1}, `{"a": [1, 4.1], "b": [2, 3], "c": {"d": "foo"}}`, nil}, 55 {f1, sql.Row{json, "$[0]", 4.1}, `[{"a": 1, "b": [2, 3], "c": {"d": "foo"}}, 4.1]`, nil}, 56 {f1, sql.Row{json, "$.[0]", 4.1}, nil, ErrInvalidPath}, 57 {f1, sql.Row{json, "foo", "test"}, nil, ErrInvalidPath}, 58 {f1, sql.Row{json, "$.c.*", "test"}, nil, ErrPathWildcard}, 59 {f1, sql.Row{json, "$.c.**", "test"}, nil, ErrPathWildcard}, 60 {f1, sql.Row{json, "$", 10.1}, `[{"a": 1, "b": [2, 3], "c": {"d": "foo"}}, 10.1]`, nil}, 61 {f1, sql.Row{nil, "$", 42.7}, nil, nil}, 62 {f1, sql.Row{json, nil, 10}, nil, nil}, 63 64 // mysql> select JSON_ARRAY_APPEND(JSON_ARRAY(1,2,3), "$[1]", 51, "$[1]", 52, "$[1]", 53); 65 // +--------------------------------------------------------------------------+ 66 // | JSON_ARRAY_APPEND(JSON_ARRAY(1,2,3), "$[1]", 51, "$[1]", 52, "$[1]", 53) | 67 // +--------------------------------------------------------------------------+ 68 // | [1, [2, 51, 52, 53], 3] | 69 // +--------------------------------------------------------------------------+ 70 {buildGetFieldExpressions(t, NewJSONArrayAppend, 7), 71 sql.Row{`[1.0,2.0,3.0]`, 72 "$[1]", 51.0, // [1, 2, 3] -> [1, [2, 51], 3] 73 "$[1]", 52.0, // [1, [2, 51], 2, 3] -> [1, [2, 51, 52] 3] 74 "$[1]", 53.0, // [1, [2, 51, 52], 3] -> [1, [2, 51, 52, 53], 3] 75 }, 76 `[1,[2, 51, 52, 53], 3]`, nil}, 77 } 78 79 for _, tstC := range testCases { 80 var paths []string 81 for _, path := range tstC.row[1:] { 82 if _, ok := path.(string); ok { 83 paths = append(paths, path.(string)) 84 } 85 } 86 87 t.Run(tstC.f.String()+"."+strings.Join(paths, ","), func(t *testing.T) { 88 req := require.New(t) 89 result, err := tstC.f.Eval(sql.NewEmptyContext(), tstC.row) 90 if tstC.err == nil { 91 req.NoError(err) 92 93 var expect interface{} 94 if tstC.expected != nil { 95 expect, _, err = types.JSON.Convert(tstC.expected) 96 if err != nil { 97 panic("Bad test string. Can't convert string to JSONDocument: " + tstC.expected.(string)) 98 } 99 } 100 101 req.Equal(expect, result) 102 } else { 103 req.Nil(result) 104 req.Error(tstC.err, err) 105 } 106 }) 107 } 108 109 }