Skip to content

Commit

Permalink
expression:add support for JSON_MERGE_PRESERVE (#8931)
Browse files Browse the repository at this point in the history
  • Loading branch information
shinytang6 authored and zz-jason committed Jan 11, 2019
1 parent 786a9d5 commit 30e8c8d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
17 changes: 16 additions & 1 deletion expression/builtin_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ func (b *builtinJSONMergeSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNu
values = append(values, value)
}
res = json.MergeBinary(values)
// function "JSON_MERGE" is deprecated since MySQL 5.7.22. Synonym for function "JSON_MERGE_PRESERVE".
// See https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge
if b.pbCode == tipb.ScalarFuncSig_JsonMergeSig {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(errDeprecatedSyntaxNoReplacement.GenWithStackByArgs("JSON_MERGE"))
}
return res, false, nil
}

Expand Down Expand Up @@ -720,7 +725,17 @@ type jsonMergePreserveFunctionClass struct {
}

func (c *jsonMergePreserveFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_MERGE_PRESERVE")
if err := c.verifyArgs(args); err != nil {
return nil, err
}
argTps := make([]types.EvalType, 0, len(args))
for range args {
argTps = append(argTps, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
sig := &builtinJSONMergeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonMergePreserveSig)
return sig, nil
}

type jsonPrettyFunctionClass struct {
Expand Down
33 changes: 33 additions & 0 deletions expression/builtin_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,39 @@ func (s *testEvaluatorSuite) TestJSONMerge(c *C) {
j2 := d.GetMysqlJSON()
cmp := json.CompareBinary(j1, j2)
c.Assert(cmp, Equals, 0, Commentf("got %v expect %v", j1.String(), j2.String()))
case nil:
c.Assert(d.IsNull(), IsTrue)
}
}
}

func (s *testEvaluatorSuite) TestJSONMergePreserve(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.JSONMergePreserve]
tbl := []struct {
Input []interface{}
Expected interface{}
}{
{[]interface{}{nil, nil}, nil},
{[]interface{}{`{}`, `[]`}, `[{}]`},
{[]interface{}{`{}`, `[]`, `3`, `"4"`}, `[{}, 3, "4"]`},
}
for _, t := range tbl {
args := types.MakeDatums(t.Input...)
f, err := fc.getFunction(s.ctx, s.datumsToConstants(args))
c.Assert(err, IsNil)
d, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)

switch x := t.Expected.(type) {
case string:
j1, err := json.ParseBinaryFromString(x)
c.Assert(err, IsNil)
j2 := d.GetMysqlJSON()
cmp := json.CompareBinary(j1, j2)
c.Assert(cmp, Equals, 0, Commentf("got %v expect %v", j1.String(), j2.String()))
case nil:
c.Assert(d.IsNull(), IsTrue)
}
}
}
Expand Down

0 comments on commit 30e8c8d

Please sign in to comment.