From fa0c5ced652cd6befe606a38eb904e4eaab3bd7e Mon Sep 17 00:00:00 2001 From: Hangjie Mo Date: Fri, 8 Sep 2023 14:50:13 +0800 Subject: [PATCH] expression, planner: check function exists with schema name (#46767) close pingcap/tidb#46744 --- errors.toml | 5 +++++ expression/builtin_encryption.go | 8 ++++---- expression/builtin_miscellaneous.go | 6 +++--- expression/builtin_test.go | 2 +- expression/distsql_builtin.go | 2 +- expression/errors.go | 2 +- expression/integration_test/integration_test.go | 5 ++--- expression/scalar_function.go | 2 +- planner/core/preprocess.go | 5 ++++- 9 files changed, 22 insertions(+), 15 deletions(-) diff --git a/errors.toml b/errors.toml index c08110c0b3dfa..94280d6a4147f 100644 --- a/errors.toml +++ b/errors.toml @@ -1916,6 +1916,11 @@ error = ''' Illegal mix of collations for operation '%s' ''' +["expression:1305"] +error = ''' +%s %s does not exist +''' + ["expression:1365"] error = ''' Division by 0 diff --git a/expression/builtin_encryption.go b/expression/builtin_encryption.go index fb451f9714cd4..6b1de33ffec2d 100644 --- a/expression/builtin_encryption.go +++ b/expression/builtin_encryption.go @@ -423,7 +423,7 @@ type desDecryptFunctionClass struct { } func (c *desDecryptFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "DES_DECRYPT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "DES_DECRYPT") } type desEncryptFunctionClass struct { @@ -431,7 +431,7 @@ type desEncryptFunctionClass struct { } func (c *desEncryptFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "DES_ENCRYPT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "DES_ENCRYPT") } type encodeFunctionClass struct { @@ -486,7 +486,7 @@ type encryptFunctionClass struct { } func (c *encryptFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "ENCRYPT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "ENCRYPT") } type oldPasswordFunctionClass struct { @@ -494,7 +494,7 @@ type oldPasswordFunctionClass struct { } func (c *oldPasswordFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "OLD_PASSWORD") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "OLD_PASSWORD") } type passwordFunctionClass struct { diff --git a/expression/builtin_miscellaneous.go b/expression/builtin_miscellaneous.go index 356dd966e4a5b..52991696e5ca1 100644 --- a/expression/builtin_miscellaneous.go +++ b/expression/builtin_miscellaneous.go @@ -466,7 +466,7 @@ type defaultFunctionClass struct { } func (c *defaultFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "DEFAULT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "DEFAULT") } type inetAtonFunctionClass struct { @@ -1084,7 +1084,7 @@ type masterPosWaitFunctionClass struct { } func (c *masterPosWaitFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "MASTER_POS_WAIT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "MASTER_POS_WAIT") } type nameConstFunctionClass struct { @@ -1308,7 +1308,7 @@ type uuidShortFunctionClass struct { } func (c *uuidShortFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "UUID_SHORT") + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "UUID_SHORT") } type vitessHashFunctionClass struct { diff --git a/expression/builtin_test.go b/expression/builtin_test.go index 77ea0814397f5..682ae03a3e849 100644 --- a/expression/builtin_test.go +++ b/expression/builtin_test.go @@ -166,7 +166,7 @@ func TestDisplayName(t *testing.T) { func newFunctionForTest(ctx sessionctx.Context, funcName string, args ...Expression) (Expression, error) { fc, ok := funcs[funcName] if !ok { - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", funcName) + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", funcName) } funcArgs := make([]Expression, len(args)) copy(funcArgs, args) diff --git a/expression/distsql_builtin.go b/expression/distsql_builtin.go index 21e662eabd04e..924d7841128c0 100644 --- a/expression/distsql_builtin.go +++ b/expression/distsql_builtin.go @@ -1086,7 +1086,7 @@ func getSignatureByPB(ctx sessionctx.Context, sigCode tipb.ScalarFuncSig, tp *ti f = &builtinInternalFromBinarySig{base} default: - e = errFunctionNotExists.GenWithStackByArgs("FUNCTION", sigCode) + e = ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", sigCode) return nil, e } f.setPbCode(sigCode) diff --git a/expression/errors.go b/expression/errors.go index 5db54963dac20..3b5dacd8dc638 100644 --- a/expression/errors.go +++ b/expression/errors.go @@ -41,9 +41,9 @@ var ( ErrInvalidJSONForFuncIndex = dbterror.ClassExpression.NewStd(mysql.ErrInvalidJSONValueForFuncIndex) ErrDataOutOfRangeFuncIndex = dbterror.ClassExpression.NewStd(mysql.ErrDataOutOfRangeFunctionalIndex) ErrFuncIndexDataIsTooLong = dbterror.ClassExpression.NewStd(mysql.ErrFunctionalIndexDataIsTooLong) + ErrFunctionNotExists = dbterror.ClassExpression.NewStd(mysql.ErrSpDoesNotExist) // All the un-exported errors are defined here: - errFunctionNotExists = dbterror.ClassExpression.NewStd(mysql.ErrSpDoesNotExist) errZlibZData = dbterror.ClassExpression.NewStd(mysql.ErrZlibZData) errZlibZBuf = dbterror.ClassExpression.NewStd(mysql.ErrZlibZBuf) errIncorrectArgs = dbterror.ClassExpression.NewStd(mysql.ErrWrongArguments) diff --git a/expression/integration_test/integration_test.go b/expression/integration_test/integration_test.go index bc0efb2c65bf2..0e38ebc41292c 100644 --- a/expression/integration_test/integration_test.go +++ b/expression/integration_test/integration_test.go @@ -3717,15 +3717,14 @@ func TestNotExistFunc(t *testing.T) { // current db is empty tk.MustGetErrMsg("SELECT xxx(1)", "[planner:1046]No database selected") - tk.MustGetErrMsg("SELECT yyy()", "[planner:1046]No database selected") + tk.MustGetErrMsg("SELECT T.upper(1)", "[expression:1305]FUNCTION t.upper does not exist") // current db is not empty tk.MustExec("use test") tk.MustGetErrMsg("SELECT xxx(1)", "[expression:1305]FUNCTION test.xxx does not exist") tk.MustGetErrMsg("SELECT yyy()", "[expression:1305]FUNCTION test.yyy does not exist") - - tk.MustExec("use test") + tk.MustGetErrMsg("SELECT t.upper(1)", "[expression:1305]FUNCTION t.upper does not exist") tk.MustGetErrMsg("SELECT timestampliteral(rand())", "[expression:1305]FUNCTION test.timestampliteral does not exist") } diff --git a/expression/scalar_function.go b/expression/scalar_function.go index a3ce92059cfb0..48e93f97fda22 100644 --- a/expression/scalar_function.go +++ b/expression/scalar_function.go @@ -214,7 +214,7 @@ func newFunctionImpl(ctx sessionctx.Context, fold int, funcName string, retType if db == "" { return nil, errors.Trace(ErrNoDB) } - return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", db+"."+funcName) + return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", db+"."+funcName) } noopFuncsMode := ctx.GetSessionVars().NoopFuncsMode if noopFuncsMode != variable.OnInt { diff --git a/planner/core/preprocess.go b/planner/core/preprocess.go index b231939ce3081..d34714036fc3c 100644 --- a/planner/core/preprocess.go +++ b/planner/core/preprocess.go @@ -354,7 +354,10 @@ func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) { if node.FnName.L == ast.NextVal || node.FnName.L == ast.LastVal || node.FnName.L == ast.SetVal { p.flag |= inSequenceFunction } - + // not support procedure right now. + if node.Schema.L != "" { + p.err = expression.ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", node.Schema.L+"."+node.FnName.L) + } case *ast.BRIEStmt: if node.Kind == ast.BRIEKindRestore { p.flag |= inCreateOrDropTable