github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/hash.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package function 16 17 import ( 18 "crypto/md5" 19 "crypto/sha1" 20 "crypto/sha256" 21 "crypto/sha512" 22 "encoding/hex" 23 "fmt" 24 "hash" 25 "io" 26 27 "github.com/dolthub/go-mysql-server/sql" 28 "github.com/dolthub/go-mysql-server/sql/expression" 29 "github.com/dolthub/go-mysql-server/sql/types" 30 ) 31 32 // MD5 function returns the MD5 hash of the input. 33 // https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_md5 34 type MD5 struct { 35 *UnaryFunc 36 } 37 38 var _ sql.FunctionExpression = (*MD5)(nil) 39 var _ sql.CollationCoercible = (*MD5)(nil) 40 41 // NewMD5 returns a new MD5 function expression 42 func NewMD5(arg sql.Expression) sql.Expression { 43 return &MD5{NewUnaryFunc(arg, "MD5", types.LongText)} 44 } 45 46 // Description implements sql.FunctionExpression 47 func (f *MD5) Description() string { 48 return "calculates MD5 checksum." 49 } 50 51 // CollationCoercibility implements the interface sql.CollationCoercible. 52 func (*MD5) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 53 return ctx.GetCollation(), 4 54 } 55 56 // Eval implements sql.Expression 57 func (f *MD5) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 58 arg, err := f.EvalChild(ctx, row) 59 if err != nil { 60 return nil, err 61 } 62 if arg == nil { 63 return nil, nil 64 } 65 66 val, _, err := types.LongText.Convert(arg) 67 if err != nil { 68 return nil, err 69 } 70 71 h := md5.New() 72 _, err = io.WriteString(h, val.(string)) 73 if err != nil { 74 return nil, err 75 } 76 return hex.EncodeToString(h.Sum(nil)), nil 77 } 78 79 // WithChildren implements sql.Expression 80 func (f *MD5) WithChildren(children ...sql.Expression) (sql.Expression, error) { 81 if len(children) != 1 { 82 return nil, sql.ErrInvalidChildrenNumber.New(f, len(children), 1) 83 } 84 return NewMD5(children[0]), nil 85 } 86 87 // SHA1 function returns the SHA1 hash of the input. 88 // https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha1 89 type SHA1 struct { 90 *UnaryFunc 91 } 92 93 var _ sql.FunctionExpression = (*SHA1)(nil) 94 var _ sql.CollationCoercible = (*SHA1)(nil) 95 96 // NewSHA1 returns a new SHA1 function expression 97 func NewSHA1(arg sql.Expression) sql.Expression { 98 return &SHA1{NewUnaryFunc(arg, "SHA1", types.LongText)} 99 } 100 101 // Description implements sql.FunctionExpression 102 func (f *SHA1) Description() string { 103 return "calculates an SHA-1 160-bit checksum." 104 } 105 106 // CollationCoercibility implements the interface sql.CollationCoercible. 107 func (*SHA1) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 108 return ctx.GetCollation(), 4 109 } 110 111 // Eval implements sql.Expression 112 func (f *SHA1) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 113 arg, err := f.EvalChild(ctx, row) 114 if err != nil { 115 return nil, err 116 } 117 if arg == nil { 118 return nil, nil 119 } 120 121 val, _, err := types.LongText.Convert(arg) 122 if err != nil { 123 return nil, err 124 } 125 126 h := sha1.New() 127 _, err = io.WriteString(h, val.(string)) 128 if err != nil { 129 return nil, err 130 } 131 return hex.EncodeToString(h.Sum(nil)), nil 132 } 133 134 // WithChildren implements sql.Expression 135 func (f *SHA1) WithChildren(children ...sql.Expression) (sql.Expression, error) { 136 if len(children) != 1 { 137 return nil, sql.ErrInvalidChildrenNumber.New(f, len(children), 1) 138 } 139 return NewSHA1(children[0]), nil 140 } 141 142 // SHA2 function returns the SHA-224/256/384/512 hash of the input. 143 // https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha2 144 type SHA2 struct { 145 expression.BinaryExpressionStub 146 } 147 148 var _ sql.FunctionExpression = (*SHA2)(nil) 149 var _ sql.CollationCoercible = (*SHA2)(nil) 150 151 // NewSHA2 returns a new SHA2 function expression 152 func NewSHA2(arg, count sql.Expression) sql.Expression { 153 return &SHA2{expression.BinaryExpressionStub{LeftChild: arg, RightChild: count}} 154 } 155 156 // Description implements sql.FunctionExpression 157 func (f *SHA2) Description() string { 158 return "calculates an SHA-2 checksum." 159 } 160 161 // CollationCoercibility implements the interface sql.CollationCoercible. 162 func (*SHA2) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 163 return ctx.GetCollation(), 4 164 } 165 166 // Eval implements sql.Expression 167 func (f *SHA2) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 168 arg, err := f.LeftChild.Eval(ctx, row) 169 if err != nil { 170 return nil, err 171 } 172 if arg == nil { 173 return nil, nil 174 } 175 countArg, err := f.RightChild.Eval(ctx, row) 176 if err != nil { 177 return nil, err 178 } 179 if countArg == nil { 180 return nil, nil 181 } 182 183 val, _, err := types.LongText.Convert(arg) 184 if err != nil { 185 return nil, err 186 } 187 count, _, err := types.Int64.Convert(countArg) 188 if err != nil { 189 return nil, err 190 } 191 192 var h hash.Hash 193 switch count.(int64) { 194 case 224: 195 h = sha256.New224() 196 case 256, 0: 197 h = sha256.New() 198 case 384: 199 h = sha512.New384() 200 case 512: 201 h = sha512.New() 202 default: 203 return nil, nil 204 } 205 206 _, err = io.WriteString(h, val.(string)) 207 if err != nil { 208 return nil, err 209 } 210 return hex.EncodeToString(h.Sum(nil)), nil 211 } 212 213 // FunctionName implements sql.FunctionExpression 214 func (f *SHA2) FunctionName() string { 215 return "sha2" 216 } 217 218 // String implements sql.Expression 219 func (f *SHA2) String() string { 220 return fmt.Sprintf("%s(%s,%s)", f.FunctionName(), f.LeftChild, f.RightChild) 221 } 222 223 // Type implements sql.Expression 224 func (f *SHA2) Type() sql.Type { 225 return types.LongText 226 } 227 228 // WithChildren implements sql.Expression 229 func (f *SHA2) WithChildren(children ...sql.Expression) (sql.Expression, error) { 230 if len(children) != 2 { 231 return nil, sql.ErrInvalidChildrenNumber.New(f, len(children), 2) 232 } 233 return NewSHA2(children[0], children[1]), nil 234 }