-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support function rpad #2270
support function rpad #2270
Changes from 3 commits
cac3530
8daa1c2
3d47547
3a45079
94b357d
f2161a0
c6265c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -603,3 603,49 @@ func trimRight(str, remstr string) string { | |
str = x | ||
} | ||
} | ||
|
||
// See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_rpad | ||
func builtinRpad(args []types.Datum, ctx context.Context) (d types.Datum, err error) { | ||
// RPAD(str,len,padstr) | ||
// args[0] string, args[1] int, args[2] string | ||
str, err := args[0].ToString() | ||
if err != nil { | ||
return d, errors.Trace(err) | ||
} | ||
length, err := args[1].ToInt64(ctx.GetSessionVars().StmtCtx) | ||
if err != nil { | ||
return d, errors.Trace(err) | ||
} | ||
l := int(length) | ||
|
||
padStr, err := args[2].ToString() | ||
if err != nil { | ||
return d, errors.Trace(err) | ||
} | ||
|
||
if len(str) >= l && l >= 0 { | ||
d.SetString(str[:l]) | ||
return d, nil | ||
} | ||
|
||
if l < 0 || len(padStr) == 0 { | ||
d.SetNull() | ||
return d, nil | ||
} | ||
|
||
tailLen := l - len(str) | ||
padStrBytes := []byte(padStr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks better. I will change. |
||
tail := make([]byte, 0, tailLen) | ||
for tailLen > len(padStr) { | ||
tail = append(tail, padStrBytes...) | ||
tailLen -= len(padStr) | ||
} | ||
if tailLen > 0 { | ||
tail = append(tail, padStrBytes[:tailLen]...) | ||
} | ||
|
||
dest := str string(tail) | ||
d.SetString(dest) | ||
|
||
return d, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -696,3 696,34 @@ func (s *testEvaluatorSuite) TestUnhexFunc(c *C) { | |
|
||
} | ||
} | ||
|
||
func (s *testEvaluatorSuite) TestRpad(c *C) { | ||
tests := []struct { | ||
str string | ||
len int64 | ||
padStr string | ||
expect interface{} | ||
}{ | ||
{"hi", 5, "?", "hi???"}, | ||
{"hi", 1, "?", "h"}, | ||
{"hi", 0, "?", ""}, | ||
{"hi", -1, "?", nil}, | ||
{"hi", 1, "", "h"}, | ||
{"hi", 5, "", nil}, | ||
{"hi", 5, "ab", "hiaba"}, | ||
{"hi", 6, "ab", "hiabab"}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test can't distinguish null and empty string. |
||
} | ||
for _, test := range tests { | ||
str := types.NewStringDatum(test.str) | ||
length := types.NewIntDatum(test.len) | ||
padStr := types.NewStringDatum(test.padStr) | ||
result, err := builtinRpad([]types.Datum{str, length, padStr}, s.ctx) | ||
c.Assert(err, IsNil) | ||
if test.expect == nil { | ||
c.Assert(result.Kind(), Equals, types.KindNull) | ||
} else { | ||
expect, _ := test.expect.(string) | ||
c.Assert(result.GetString(), Equals, expect) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, the following logic too much complex than it should be, and the loop is hard to read.
Here is a simpler example:
just check
pad != ""
before this logic.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, it is simpler indeed. I worried that
str = str pad
would allocate memory every time, so I chose pre-allocated []byte.