diff --git a/DEPS.bzl b/DEPS.bzl index 39b7c9e484d56..8c9807e059dd1 100644 --- a/DEPS.bzl +++ b/DEPS.bzl @@ -2991,8 +2991,8 @@ def go_deps(): name = "com_github_pingcap_tipb", build_file_proto_mode = "disable_global", importpath = "github.com/pingcap/tipb", - sum = "h1:DbmCfCbcavo0JG+gSp0ySvv1ub/c/j3hsnYzyYPzONo=", - version = "v0.0.0-20221123081521-2fb828910813", + sum = "h1:j5sw2YZY7QfgIFZEoUcn1P5cYflms1PCVVS96i+IQiI=", + version = "v0.0.0-20230119054146-c6b7a5a1623b", ) go_repository( name = "com_github_pkg_browser", diff --git a/errno/errcode.go b/errno/errcode.go index 0d05c6a63f7af..0501bc0020e07 100644 --- a/errno/errcode.go +++ b/errno/errcode.go @@ -922,6 +922,7 @@ const ( ErrFunctionalIndexNotApplicable = 3909 ErrDynamicPrivilegeNotRegistered = 3929 ErUserAccessDeniedForUserAccountBlockedByPasswordLock = 3955 + ErrJSONInBooleanContext = 3986 ErrTableWithoutPrimaryKey = 3750 // MariaDB errors. ErrOnlyOneDefaultPartionAllowed = 4030 diff --git a/errno/errname.go b/errno/errname.go index 1c14f4517e247..a75ac71a6b212 100644 --- a/errno/errname.go +++ b/errno/errname.go @@ -924,6 +924,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrInvalidRequiresSingleReference: mysql.Message("In recursive query block of Recursive Common Table Expression '%s', the recursive table must be referenced only once, and not in any subquery", nil), ErrCTEMaxRecursionDepth: mysql.Message("Recursive query aborted after %d iterations. Try increasing @@cte_max_recursion_depth to a larger value", nil), ErrTableWithoutPrimaryKey: mysql.Message("Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting.", nil), + ErrJSONInBooleanContext: mysql.Message("Evaluating a JSON value in SQL boolean context does an implicit comparison against JSON integer 0; if this is not what you want, consider converting JSON to a SQL numeric type with JSON_VALUE RETURNING", nil), // MariaDB errors. ErrOnlyOneDefaultPartionAllowed: mysql.Message("Only one DEFAULT partition allowed", nil), ErrWrongPartitionTypeExpectedSystemTime: mysql.Message("Wrong partitioning type, expected type: `SYSTEM_TIME`", nil), diff --git a/expression/builtin_op.go b/expression/builtin_op.go index cbb2afcc9377a..e15d1730c8cd9 100644 --- a/expression/builtin_op.go +++ b/expression/builtin_op.go @@ -718,7 +718,7 @@ func (c *unaryNotFunctionClass) getFunction(ctx sessionctx.Context, args []Expre argTp := args[0].GetType().EvalType() if argTp == types.ETTimestamp || argTp == types.ETDatetime || argTp == types.ETDuration { argTp = types.ETInt - } else if argTp == types.ETJson || argTp == types.ETString { + } else if argTp == types.ETString { argTp = types.ETReal } @@ -739,6 +739,10 @@ func (c *unaryNotFunctionClass) getFunction(ctx sessionctx.Context, args []Expre case types.ETInt: sig = &builtinUnaryNotIntSig{bf} sig.setPbCode(tipb.ScalarFuncSig_UnaryNotInt) + case types.ETJson: + ctx.GetSessionVars().StmtCtx.AppendWarning(errJSONInBooleanContext) + sig = &builtinUnaryNotJSONSig{bf} + sig.setPbCode(tipb.ScalarFuncSig_UnaryNotJSON) default: return nil, errors.Errorf("unexpected types.EvalType %v", argTp) } @@ -808,6 +812,28 @@ func (b *builtinUnaryNotIntSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, false, nil } +type builtinUnaryNotJSONSig struct { + baseBuiltinFunc +} + +func (b *builtinUnaryNotJSONSig) Clone() builtinFunc { + newSig := &builtinUnaryNotJSONSig{} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +func (b *builtinUnaryNotJSONSig) evalInt(row chunk.Row) (int64, bool, error) { + arg, isNull, err := b.args[0].EvalJSON(b.ctx, row) + if isNull || err != nil { + return 0, true, err + } + + if types.CompareBinaryJSON(arg, types.CreateBinaryJSON(int64(0))) == 0 { + return 1, false, nil + } + return 0, false, nil +} + type unaryMinusFunctionClass struct { baseFunctionClass } diff --git a/expression/builtin_op_test.go b/expression/builtin_op_test.go index 04024c90cb70f..c771b95da89d3 100644 --- a/expression/builtin_op_test.go +++ b/expression/builtin_op_test.go @@ -462,6 +462,8 @@ func TestUnaryNot(t *testing.T) { {[]interface{}{"0.3"}, 0, false, false}, {[]interface{}{types.NewDecFromFloatForTest(0.3)}, 0, false, false}, {[]interface{}{nil}, 0, true, false}, + {[]interface{}{types.CreateBinaryJSON(int64(0))}, 1, false, false}, + {[]interface{}{types.CreateBinaryJSON(map[string]interface{}{"test": "test"})}, 0, false, false}, {[]interface{}{errors.New("must error")}, 0, false, true}, } diff --git a/expression/errors.go b/expression/errors.go index 62d5b89d547b9..536ef065d7664 100644 --- a/expression/errors.go +++ b/expression/errors.go @@ -60,6 +60,7 @@ var ( errSpecificAccessDenied = dbterror.ClassExpression.NewStd(mysql.ErrSpecificAccessDenied) errUserLockDeadlock = dbterror.ClassExpression.NewStd(mysql.ErrUserLockDeadlock) errUserLockWrongName = dbterror.ClassExpression.NewStd(mysql.ErrUserLockWrongName) + errJSONInBooleanContext = dbterror.ClassExpression.NewStd(mysql.ErrJSONInBooleanContext) // Sequence usage privilege check. errSequenceAccessDenied = dbterror.ClassExpression.NewStd(mysql.ErrTableaccessDenied) diff --git a/go.mod b/go.mod index 2e6cbf201b043..074527280c3de 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/pingcap/log v1.1.1-0.20221116035753-734d527bc87c github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4 github.com/pingcap/tidb/parser v0.0.0-20211011031125-9b13dc409c5e - github.com/pingcap/tipb v0.0.0-20221123081521-2fb828910813 + github.com/pingcap/tipb v0.0.0-20230119054146-c6b7a5a1623b github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 diff --git a/go.sum b/go.sum index a75624ea224ee..7acd2bfd5792d 100644 --- a/go.sum +++ b/go.sum @@ -794,8 +794,8 @@ github.com/pingcap/log v1.1.1-0.20221116035753-734d527bc87c h1:crhkw6DD+07Bg1wYh github.com/pingcap/log v1.1.1-0.20221116035753-734d527bc87c/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4 h1:HYbcxtnkN3s5tqrZ/z3eJS4j3Db8wMphEm1q10lY/TM= github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4/go.mod h1:sDCsM39cGiv2vwunZkaFA917vVkqDTGSPbbV7z4Oops= -github.com/pingcap/tipb v0.0.0-20221123081521-2fb828910813 h1:DbmCfCbcavo0JG+gSp0ySvv1ub/c/j3hsnYzyYPzONo= -github.com/pingcap/tipb v0.0.0-20221123081521-2fb828910813/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= +github.com/pingcap/tipb v0.0.0-20230119054146-c6b7a5a1623b h1:j5sw2YZY7QfgIFZEoUcn1P5cYflms1PCVVS96i+IQiI= +github.com/pingcap/tipb v0.0.0-20230119054146-c6b7a5a1623b/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=