Skip to content

Commit

Permalink
expression: fix wrong flen from baseFunctionClass (#56607)
Browse files Browse the repository at this point in the history
close #56587
  • Loading branch information
joechenrh authored Nov 19, 2024
1 parent 35d5739 commit 60bbccb
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
4 changes: 4 additions & 0 deletions pkg/executor/test/issuetest/executor_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func TestUnionIssue(t *testing.T) {
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (id int);")
tk.MustExec("create table t2 (id int, c int);")
// Issue56587
tk.MustQuery("select quote(cast('abc' as char)) union all select '1'").Check(testkit.Rows("'abc'", "1"))
tk.MustQuery(`select elt(2, "1", cast('abc' as char)) union all select "12" where false`).Check(testkit.Rows("abc"))
tk.MustQuery(`select hex(cast('1' as char)) union all select '1';`).Check(testkit.Rows("31", "1"))

testCases := []struct {
sql string
Expand Down
23 changes: 18 additions & 5 deletions pkg/expression/builtin_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -1703,21 +1703,28 @@ func (c *hexFunctionClass) getFunction(ctx BuildContext, args []Expression) (bui
switch argTp {
case types.ETString, types.ETDatetime, types.ETTimestamp, types.ETDuration, types.ETJson:
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
bf.tp.SetFlen(types.UnspecifiedLength)
if err != nil {
return nil, err
}
argFieldTp := args[0].GetType(ctx.GetEvalCtx())
argLen := args[0].GetType(ctx.GetEvalCtx()).GetFlen()
// Use UTF8MB4 as default.
bf.tp.SetFlen(argFieldTp.GetFlen() * 4 * 2)
if argLen != types.UnspecifiedLength {
bf.tp.SetFlen(argLen * 4 * 2)
}
sig := &builtinHexStrArgSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_HexStrArg)
return sig, nil
case types.ETInt, types.ETReal, types.ETDecimal:
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
bf.tp.SetFlen(types.UnspecifiedLength)
if err != nil {
return nil, err
}
bf.tp.SetFlen(args[0].GetType(ctx.GetEvalCtx()).GetFlen() * 2)
argLen := args[0].GetType(ctx.GetEvalCtx()).GetFlen()
if argLen != types.UnspecifiedLength {
bf.tp.SetFlen(argLen * 2)
}
charset, collate := ctx.GetCharsetInfo()
bf.tp.SetCharset(charset)
bf.tp.SetCollate(collate)
Expand Down Expand Up @@ -3072,7 +3079,12 @@ func (c *quoteFunctionClass) getFunction(ctx BuildContext, args []Expression) (b
return nil, err
}
SetBinFlagOrBinStr(args[0].GetType(ctx.GetEvalCtx()), bf.tp)
bf.tp.SetFlen(2*args[0].GetType(ctx.GetEvalCtx()).GetFlen() + 2)
flen := args[0].GetType(ctx.GetEvalCtx()).GetFlen()
newFlen := 2*flen + 2
if flen == types.UnspecifiedLength {
newFlen = types.UnspecifiedLength
}
bf.tp.SetFlen(newFlen)
if bf.tp.GetFlen() > mysql.MaxBlobWidth {
bf.tp.SetFlen(mysql.MaxBlobWidth)
}
Expand Down Expand Up @@ -3201,7 +3213,8 @@ func (c *eltFunctionClass) getFunction(ctx BuildContext, args []Expression) (bui
if types.IsBinaryStr(argType) {
types.SetBinChsClnFlag(bf.tp)
}
if argType.GetFlen() > bf.tp.GetFlen() {
flen := argType.GetFlen()
if flen == types.UnspecifiedLength || flen > bf.tp.GetFlen() {
bf.tp.SetFlen(argType.GetFlen())
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/expression/typeinfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,8 +483,8 @@ func (s *InferTypeSuite) createTestCase4StrFuncs() []typeInferTestCase {

{"quote(c_int_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, 42, types.UnspecifiedLength},
{"quote(c_bigint_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, 42, types.UnspecifiedLength},
{"quote(c_float_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, 0, types.UnspecifiedLength},
{"quote(c_double_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, 0, types.UnspecifiedLength},
{"quote(c_float_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, types.UnspecifiedLength, types.UnspecifiedLength},
{"quote(c_double_d )", mysql.TypeVarString, charset.CharsetUTF8MB4, 0, types.UnspecifiedLength, types.UnspecifiedLength},

{"convert(c_double_d using utf8mb4)", mysql.TypeLongBlob, charset.CharsetUTF8MB4, 0, mysql.MaxBlobWidth, types.UnspecifiedLength},
{"convert(c_binary using utf8mb4)", mysql.TypeLongBlob, charset.CharsetUTF8MB4, 0, mysql.MaxBlobWidth, types.UnspecifiedLength},
Expand Down

0 comments on commit 60bbccb

Please sign in to comment.