Skip to content

Commit

Permalink
builtin: add sha/sha1 built-in function (pingcap#2781)
Browse files Browse the repository at this point in the history
* mod: add sha/sha1 built-in function

* Address comment

* unify  return style

* address comments, add some test cases
  • Loading branch information
c4pt0r authored and coocood committed Mar 5, 2017
1 parent 0391820 commit 8934e0c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 4 deletions.
27 changes: 23 additions & 4 deletions expression/builtin_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package expression

import (
"crypto/md5"
"crypto/sha1"
"fmt"

"github.com/juju/errors"
Expand Down Expand Up @@ -105,12 +106,12 @@ type builtinAesDecryptSig struct {
func (b *builtinAesDecryptSig) eval(row []types.Datum) (d types.Datum, err error) {
args, err := b.evalArgs(row)
if err != nil {
return types.Datum{}, errors.Trace(err)
return d, errors.Trace(err)
}
for _, arg := range args {
// If either function argument is NULL, the function returns NULL.
if arg.IsNull() {
return
return d, nil
}
}
cryptStr := args[0].GetBytes()
Expand All @@ -123,7 +124,7 @@ func (b *builtinAesDecryptSig) eval(row []types.Datum) (d types.Datum, err error
return d, errors.Trace(err)
}
d.SetString(string(data))
return
return d, nil
}

type aesEncryptFunctionClass struct {
Expand Down Expand Up @@ -533,8 +534,26 @@ type builtinSHA1Sig struct {
}

// See https://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html#function_sha1
// The value is returned as a string of 40 hexadecimal digits, or NULL if the argument was NULL.
func (b *builtinSHA1Sig) eval(row []types.Datum) (d types.Datum, err error) {
return d, errFunctionNotExists.GenByArgs("SHA1")
args, err := b.evalArgs(row)
if err != nil {
return types.Datum{}, errors.Trace(err)
}
// SHA/SHA1 function only accept 1 parameter
arg := args[0]
if arg.IsNull() {
return d, nil
}
bin, err := arg.ToBytes()
if err != nil {
return d, errors.Trace(err)
}
hasher := sha1.New()
hasher.Write(bin)
data := fmt.Sprintf("%x", hasher.Sum(nil))
d.SetString(data)
return d, nil
}

type sha2FunctionClass struct {
Expand Down
32 changes: 32 additions & 0 deletions expression/builtin_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@ var md5Cases = []md5Test{
{nil, nil},
}

var shaCases = []struct {
origin interface{}
crypt string
}{
{"test", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"},
{"c4pt0r", "034923dcabf099fc4c8917c0ab91ffcd4c2578a6"},
{"pingcap", "73bf9ef43a44f42e2ea2894d62f0917af149a006"},
{"foobar", "8843d7f92416211de9ebb963ff4ce28125932878"},
{1024, "128351137a9c47206c4507dcf2e6fbeeca3a9079"},
{123.45, "22f8b438ad7e89300b51d88684f3f0b9fa1d7a32"},
}

func (s *testEvaluatorSuite) TestShaEncrypt(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.SHA]
for _, test := range shaCases {
in := types.NewDatum(test.origin)
f, _ := fc.getFunction(datumsToConstants([]types.Datum{in}), s.ctx)
crypt, err := f.eval(nil)
c.Assert(err, IsNil)
res, err := crypt.ToString()
c.Assert(err, IsNil)
c.Assert(res, Equals, test.crypt)
}
// test NULL input for sha
var argNull types.Datum
f, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)
crypt, err := f.eval(nil)
c.Assert(err, IsNil)
c.Assert(crypt.IsNull(), IsTrue)
}

func (s *testEvaluatorSuite) TestAESEncrypt(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.AesEncrypt]
Expand Down
4 changes: 4 additions & 0 deletions plan/typeinferer.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) {
tp = types.NewFieldType(mysql.TypeVarString)
chs = v.defaultCharset
tp.Flen = 32
case ast.SHA, ast.SHA1:
tp = types.NewFieldType(mysql.TypeVarString)
chs = v.defaultCharset
tp.Flen = 40
default:
tp = types.NewFieldType(mysql.TypeUnspecified)
}
Expand Down
2 changes: 2 additions & 0 deletions plan/typeinferer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) {
{`aes_encrypt("pingcap", "fit2cloud@2014")`, mysql.TypeVarString, "utf8"},
{`aes_decrypt("pingcap", "fit2cloud@2014")`, mysql.TypeVarString, "utf8"},
{`md5(123)`, mysql.TypeVarString, "utf8"},
{`sha1(123)`, mysql.TypeVarString, "utf8"},
{`sha(123)`, mysql.TypeVarString, "utf8"},
}
for _, ca := range cases {
ctx := testKit.Se.(context.Context)
Expand Down

0 comments on commit 8934e0c

Please sign in to comment.