Skip to content

Commit f06bd7e

Browse files
committed
add unwrap on json convert and test
1 parent 312762f commit f06bd7e

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

enginetest/queries/json_scripts.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,35 @@
1515
package queries
1616

1717
import (
18+
"github.com/dolthub/go-mysql-server/sql/plan"
1819
"github.com/dolthub/vitess/go/vt/sqlparser"
1920

2021
"github.com/dolthub/go-mysql-server/sql"
2122
"github.com/dolthub/go-mysql-server/sql/types"
2223
)
2324

2425
var JsonScripts = []ScriptTest{
26+
{
27+
Name: "TextStorage converts to JSON when using dolt wrapper",
28+
SetUpScript: []string{
29+
"CREATE TABLE pages (id INT PRIMARY KEY, text_col TEXT, text_json JSON)",
30+
"INSERT INTO pages VALUES (1, '{\"message\":\"hello\"}', NULL)",
31+
},
32+
Assertions: []ScriptTestAssertion{
33+
{
34+
Query: "UPDATE pages SET text_json = text_col",
35+
Expected: []sql.Row{
36+
{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}},
37+
},
38+
},
39+
{
40+
Query: "SELECT text_json FROM pages",
41+
Expected: []sql.Row{
42+
{types.MustJSON("{\"message\":\"hello\"}")},
43+
},
44+
},
45+
},
46+
},
2547
{
2648
Name: "json_type scripts",
2749
Assertions: []ScriptTestAssertion{

sql/types/json.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ func (t JsonType) Convert(c context.Context, v interface{}) (doc interface{}, in
6868
if err != nil {
6969
return nil, sql.OutOfRange, sql.ErrInvalidJson.New(err.Error())
7070
}
71+
// Text values may be stored in wrappers (e.g. Dolt's TextStorage), so unwrap to the raw string before decoding.
72+
case sql.StringWrapper:
73+
str, err := v.Unwrap(c)
74+
if err != nil {
75+
return nil, sql.OutOfRange, err
76+
}
77+
charsetMaxLength := sql.Collation_Default.CharacterSet().MaxLength()
78+
length := int64(len(str)) * charsetMaxLength
79+
if length > MaxJsonFieldByteLength {
80+
return nil, sql.InRange, ErrLengthTooLarge.New(length, MaxJsonFieldByteLength)
81+
}
82+
err = json.Unmarshal([]byte(str), &doc)
83+
if err != nil {
84+
return nil, sql.OutOfRange, sql.ErrInvalidJson.New(err.Error())
85+
}
7186
case int8:
7287
return JSONDocument{Val: int64(v)}, sql.InRange, nil
7388
case int16:

sql/types/jsontests/json_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,34 @@ import (
2828
"github.com/dolthub/go-mysql-server/sql/types"
2929
)
3030

31+
type mockStringWrapper struct {
32+
val string
33+
}
34+
35+
func (m mockStringWrapper) Unwrap(ctx context.Context) (string, error) {
36+
return m.val, nil
37+
}
38+
39+
func (m mockStringWrapper) UnwrapAny(ctx context.Context) (interface{}, error) {
40+
return m.val, nil
41+
}
42+
43+
func (m mockStringWrapper) IsExactLength() bool {
44+
return false
45+
}
46+
47+
func (m mockStringWrapper) MaxByteLength() int64 {
48+
return int64(len(m.val))
49+
}
50+
51+
func (m mockStringWrapper) Compare(ctx context.Context, other interface{}) (int, bool, error) {
52+
return 0, false, nil
53+
}
54+
55+
func (m mockStringWrapper) Hash() interface{} {
56+
return m.val
57+
}
58+
3159
func TestJsonCompare(t *testing.T) {
3260
RunJsonCompareTests(t, JsonCompareTests, func(t *testing.T, left, right interface{}) (interface{}, interface{}) {
3361
return ConvertToJson(t, left), ConvertToJson(t, right)
@@ -58,6 +86,7 @@ func TestJsonConvert(t *testing.T) {
5886
{types.MustJSON(`{"field":"test"}`), types.MustJSON(`{"field":"test"}`), false},
5987
{[]string{}, types.MustJSON(`[]`), false},
6088
{[]string{`555-555-5555`}, types.MustJSON(`["555-555-5555"]`), false},
89+
{mockStringWrapper{val: `{"c": 1}`}, types.MustJSON(`{"c":1}`), false},
6190
}
6291

6392
for _, test := range tests {

0 commit comments

Comments
 (0)