From bdb30135b6df1d17dd32dc8059f682fc9b4082a5 Mon Sep 17 00:00:00 2001 From: kanchairen Date: Fri, 12 Jul 2019 20:06:14 +0800 Subject: [PATCH] Function INSERT should be NULL if any argument is NULL. (#11174) --- expression/builtin_string.go | 18 ++++++------ expression/builtin_string_test.go | 49 +++++++++++++++++++++++++++++++ expression/integration_test.go | 4 +++ 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/expression/builtin_string.go b/expression/builtin_string.go index 9836213b1bca0..1bc4a80dd3e89 100644 --- a/expression/builtin_string.go +++ b/expression/builtin_string.go @@ -3270,15 +3270,11 @@ func (b *builtinInsertBinarySig) evalString(row chunk.Row) (string, bool, error) if isNull || err != nil { return "", true, errors.Trace(err) } - strLength := int64(len(str)) pos, isNull, err := b.args[1].EvalInt(b.ctx, row) if isNull || err != nil { return "", true, errors.Trace(err) } - if pos < 1 || pos > strLength { - return str, false, nil - } length, isNull, err := b.args[2].EvalInt(b.ctx, row) if isNull || err != nil { @@ -3290,6 +3286,10 @@ func (b *builtinInsertBinarySig) evalString(row chunk.Row) (string, bool, error) return "", true, errors.Trace(err) } + strLength := int64(len(str)) + if pos < 1 || pos > strLength { + return str, false, nil + } if length > strLength-pos+1 || length < 0 { length = strLength - pos + 1 } @@ -3321,16 +3321,11 @@ func (b *builtinInsertSig) evalString(row chunk.Row) (string, bool, error) { if isNull || err != nil { return "", true, errors.Trace(err) } - runes := []rune(str) - runeLength := int64(len(runes)) pos, isNull, err := b.args[1].EvalInt(b.ctx, row) if isNull || err != nil { return "", true, errors.Trace(err) } - if pos < 1 || pos > runeLength { - return str, false, nil - } length, isNull, err := b.args[2].EvalInt(b.ctx, row) if isNull || err != nil { @@ -3342,6 +3337,11 @@ func (b *builtinInsertSig) evalString(row chunk.Row) (string, bool, error) { return "", true, errors.Trace(err) } + runes := []rune(str) + runeLength := int64(len(runes)) + if pos < 1 || pos > runeLength { + return str, false, nil + } if length > runeLength-pos+1 || length < 0 { length = runeLength - pos + 1 } diff --git a/expression/builtin_string_test.go b/expression/builtin_string_test.go index dde116f05f89c..3b0f5a9ff077a 100644 --- a/expression/builtin_string_test.go +++ b/expression/builtin_string_test.go @@ -1474,12 +1474,32 @@ func (s *testEvaluatorSuite) TestInsertBinarySig(c *C) { input := chunk.NewChunkWithCapacity(colTypes, 2) input.AppendString(0, "abc") input.AppendString(0, "abc") + input.AppendString(0, "abc") + input.AppendNull(0) + input.AppendString(0, "abc") + input.AppendString(0, "abc") + input.AppendString(0, "abc") + input.AppendInt64(1, 3) input.AppendInt64(1, 3) + input.AppendInt64(1, 0) input.AppendInt64(1, 3) + input.AppendNull(1) + input.AppendInt64(1, 3) + input.AppendInt64(1, 3) + input.AppendInt64(2, -1) + input.AppendInt64(2, -1) input.AppendInt64(2, -1) input.AppendInt64(2, -1) + input.AppendInt64(2, -1) + input.AppendNull(2) + input.AppendInt64(2, -1) input.AppendString(3, "d") input.AppendString(3, "de") + input.AppendString(3, "d") + input.AppendString(3, "d") + input.AppendString(3, "d") + input.AppendString(3, "d") + input.AppendNull(3) res, isNull, err := insert.evalString(input.GetRow(0)) c.Assert(res, Equals, "abd") @@ -1491,6 +1511,31 @@ func (s *testEvaluatorSuite) TestInsertBinarySig(c *C) { c.Assert(isNull, IsTrue) c.Assert(err, IsNil) + res, isNull, err = insert.evalString(input.GetRow(2)) + c.Assert(res, Equals, "abc") + c.Assert(isNull, IsFalse) + c.Assert(err, IsNil) + + res, isNull, err = insert.evalString(input.GetRow(3)) + c.Assert(res, Equals, "") + c.Assert(isNull, IsTrue) + c.Assert(err, IsNil) + + res, isNull, err = insert.evalString(input.GetRow(4)) + c.Assert(res, Equals, "") + c.Assert(isNull, IsTrue) + c.Assert(err, IsNil) + + res, isNull, err = insert.evalString(input.GetRow(5)) + c.Assert(res, Equals, "") + c.Assert(isNull, IsTrue) + c.Assert(err, IsNil) + + res, isNull, err = insert.evalString(input.GetRow(6)) + c.Assert(res, Equals, "") + c.Assert(isNull, IsTrue) + c.Assert(err, IsNil) + warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings() c.Assert(len(warnings), Equals, 1) lastWarn := warnings[len(warnings)-1] @@ -1848,6 +1893,8 @@ func (s *testEvaluatorSuite) TestInsert(c *C) { {[]interface{}{"Quadratic", 3, 4, nil}, nil}, {[]interface{}{"Quadratic", 3, -1, "What"}, "QuWhat"}, {[]interface{}{"Quadratic", 3, 1, "What"}, "QuWhatdratic"}, + {[]interface{}{"Quadratic", -1, nil, "What"}, nil}, + {[]interface{}{"Quadratic", -1, 4, nil}, nil}, {[]interface{}{"我叫小雨呀", 3, 2, "王雨叶"}, "我叫王雨叶呀"}, {[]interface{}{"我叫小雨呀", -1, 2, "王雨叶"}, "我叫小雨呀"}, @@ -1858,6 +1905,8 @@ func (s *testEvaluatorSuite) TestInsert(c *C) { {[]interface{}{"我叫小雨呀", 3, 4, nil}, nil}, {[]interface{}{"我叫小雨呀", 3, -1, "王雨叶"}, "我叫王雨叶"}, {[]interface{}{"我叫小雨呀", 3, 1, "王雨叶"}, "我叫王雨叶雨呀"}, + {[]interface{}{"我叫小雨呀", -1, nil, "王雨叶"}, nil}, + {[]interface{}{"我叫小雨呀", -1, 2, nil}, nil}, } fc := funcs[ast.InsertFunc] for _, test := range tests { diff --git a/expression/integration_test.go b/expression/integration_test.go index 171ab7db4499f..be14c40c421a2 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -918,6 +918,10 @@ func (s *testIntegrationSuite) TestStringBuiltin(c *C) { result.Check(testkit.Rows("aaa文 ba aaa ba")) result = tk.MustQuery(`select insert("bb", NULL, 1, "aa"), insert("bb", 1, NULL, "aa"), insert(NULL, 1, 1, "aaa"), insert("bb", 1, 1, NULL);`) result.Check(testkit.Rows(" ")) + result = tk.MustQuery(`SELECT INSERT("bb", 0, 1, NULL), INSERT("bb", 0, NULL, "aaa");`) + result.Check(testkit.Rows(" ")) + result = tk.MustQuery(`SELECT INSERT("中文", 0, 1, NULL), INSERT("中文", 0, NULL, "aaa");`) + result.Check(testkit.Rows(" ")) // for export_set result = tk.MustQuery(`select export_set(7, "1", "0", ",", 65);`)