From 47fe9e1b1eaea9d3b209680880c95787579355d1 Mon Sep 17 00:00:00 2001 From: HuaiyuXu <391585975@qq.com> Date: Wed, 12 Dec 2018 17:18:58 +0800 Subject: [PATCH] expression: do not set ParseToJSONFlag to a JSON column (#8564) (#8660) --- expression/builtin_compare.go | 2 +- expression/builtin_json.go | 13 ++++++------- expression/util.go | 12 ++++++++++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/expression/builtin_compare.go b/expression/builtin_compare.go index 4f641844f3d5e..024dad45f482e 100644 --- a/expression/builtin_compare.go +++ b/expression/builtin_compare.go @@ -1170,7 +1170,7 @@ func (c *compareFunctionClass) generateCmpSigs(ctx sessionctx.Context, args []Ex if tp == types.ETJson { // In compare, if we cast string to JSON, we shouldn't parse it. for i := range args { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } } bf.tp.Flen = 1 diff --git a/expression/builtin_json.go b/expression/builtin_json.go index 184f179aaa927..3869a1be8bcf7 100644 --- a/expression/builtin_json.go +++ b/expression/builtin_json.go @@ -16,7 +16,6 @@ package expression import ( "github.com/pingcap/errors" "github.com/pingcap/parser/ast" - "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" @@ -171,7 +170,7 @@ func (c *jsonUnquoteFunctionClass) getFunction(ctx sessionctx.Context, args []Ex return nil, errors.Trace(err) } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETString, types.ETJson) - args[0].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[0]) sig := &builtinJSONUnquoteSig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonUnquoteSig) return sig, nil @@ -215,7 +214,7 @@ func (c *jsonSetFunctionClass) getFunction(ctx sessionctx.Context, args []Expres } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...) for i := 2; i < len(args); i += 2 { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } sig := &builtinJSONSetSig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonSetSig) @@ -255,7 +254,7 @@ func (c *jsonInsertFunctionClass) getFunction(ctx sessionctx.Context, args []Exp } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...) for i := 2; i < len(args); i += 2 { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } sig := &builtinJSONInsertSig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonInsertSig) @@ -295,7 +294,7 @@ func (c *jsonReplaceFunctionClass) getFunction(ctx sessionctx.Context, args []Ex } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...) for i := 2; i < len(args); i += 2 { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } sig := &builtinJSONReplaceSig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonReplaceSig) @@ -431,7 +430,7 @@ func (c *jsonObjectFunctionClass) getFunction(ctx sessionctx.Context, args []Exp } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...) for i := 1; i < len(args); i += 2 { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } sig := &builtinJSONObjectSig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonObjectSig) @@ -494,7 +493,7 @@ func (c *jsonArrayFunctionClass) getFunction(ctx sessionctx.Context, args []Expr } bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...) for i := range args { - args[i].GetType().Flag &= ^mysql.ParseToJSONFlag + DisableParseJSONFlag4Expr(args[i]) } sig := &builtinJSONArraySig{bf} sig.setPbCode(tipb.ScalarFuncSig_JsonArraySig) diff --git a/expression/util.go b/expression/util.go index 73a3662268fa8..b4fbfe9adb86e 100644 --- a/expression/util.go +++ b/expression/util.go @@ -503,3 +503,15 @@ func ColumnSliceIsIntersect(s1, s2 []*Column) bool { } return false } + +// DisableParseJSONFlag4Expr disables ParseToJSONFlag for `expr` except Column. +// We should not *PARSE* a string as JSON under some scenarios. ParseToJSONFlag +// is 0 for JSON column yet, so we can skip it. Moreover, Column.RetType refers +// to the infoschema, if we modify it, data race may happen if another goroutine +// read from the infoschema at the same time. +func DisableParseJSONFlag4Expr(expr Expression) { + if _, isColumn := expr.(*Column); isColumn { + return + } + expr.GetType().Flag &= ^mysql.ParseToJSONFlag +}