Skip to content

Commit c37778a

Browse files
authored
*: Add Digest struct to get bytes of digest (pingcap#1231)
1 parent f5c77b7 commit c37778a

File tree

2 files changed

+79
-19
lines changed

2 files changed

+79
-19
lines changed

digester.go

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package parser
1616
import (
1717
"bytes"
1818
"crypto/sha256"
19-
"fmt"
19+
"encoding/hex"
2020
hash2 "hash"
2121
"reflect"
2222
"strings"
@@ -27,16 +27,39 @@ import (
2727
"github.com/pingcap/parser/charset"
2828
)
2929

30+
type Digest struct {
31+
b []byte
32+
str string
33+
}
34+
35+
// NewDigest returns a new digest.
36+
func NewDigest(b []byte) *Digest {
37+
return &Digest{
38+
b: b,
39+
str: hex.EncodeToString(b),
40+
}
41+
}
42+
43+
// String returns the digest hex string.
44+
func (d *Digest) String() string {
45+
return d.str
46+
}
47+
48+
// Bytes returns the digest byte slice.
49+
func (d *Digest) Bytes() []byte {
50+
return d.b
51+
}
52+
3053
// DigestHash generates the digest of statements.
3154
// it will generate a hash on normalized form of statement text
3255
// which removes general property of a statement but keeps specific property.
3356
//
3457
// for example: both DigestHash('select 1') and DigestHash('select 2') => e1c71d1661ae46e09b7aaec1c390957f0d6260410df4e4bc71b9c8d681021471
3558
//
3659
// Deprecated: It is logically consistent with NormalizeDigest.
37-
func DigestHash(sql string) (result string) {
60+
func DigestHash(sql string) (digest *Digest) {
3861
d := digesterPool.Get().(*sqlDigester)
39-
result = d.doDigest(sql)
62+
digest = d.doDigest(sql)
4063
digesterPool.Put(d)
4164
return
4265
}
@@ -48,9 +71,9 @@ func DigestHash(sql string) (result string) {
4871
// for example: DigestNormalized('select ?')
4972
// DigestNormalized should be called with a normalized SQL string (like 'select ?') generated by function Normalize.
5073
// do not call with SQL which is not normalized, DigestNormalized('select 1') and DigestNormalized('select 2') is not the same
51-
func DigestNormalized(normalized string) (result string) {
74+
func DigestNormalized(normalized string) (digest *Digest) {
5275
d := digesterPool.Get().(*sqlDigester)
53-
result = d.doDigestNormalized(normalized)
76+
digest = d.doDigestNormalized(normalized)
5477
digesterPool.Put(d)
5578
return
5679
}
@@ -68,7 +91,7 @@ func Normalize(sql string) (result string) {
6891
}
6992

7093
// NormalizeDigest combines Normalize and DigestNormalized into one method.
71-
func NormalizeDigest(sql string) (normalized, digest string) {
94+
func NormalizeDigest(sql string) (normalized string, digest *Digest) {
7295
d := digesterPool.Get().(*sqlDigester)
7396
normalized, digest = d.doNormalizeDigest(sql)
7497
digesterPool.Put(d)
@@ -92,24 +115,24 @@ type sqlDigester struct {
92115
tokens tokenDeque
93116
}
94117

95-
func (d *sqlDigester) doDigestNormalized(normalized string) (result string) {
118+
func (d *sqlDigester) doDigestNormalized(normalized string) (digest *Digest) {
96119
hdr := *(*reflect.StringHeader)(unsafe.Pointer(&normalized))
97120
b := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
98121
Data: hdr.Data,
99122
Len: hdr.Len,
100123
Cap: hdr.Len,
101124
}))
102125
d.hasher.Write(b)
103-
result = fmt.Sprintf("%x", d.hasher.Sum(nil))
126+
digest = NewDigest(d.hasher.Sum(nil))
104127
d.hasher.Reset()
105128
return
106129
}
107130

108-
func (d *sqlDigester) doDigest(sql string) (result string) {
131+
func (d *sqlDigester) doDigest(sql string) (digest *Digest) {
109132
d.normalize(sql)
110133
d.hasher.Write(d.buffer.Bytes())
111134
d.buffer.Reset()
112-
result = fmt.Sprintf("%x", d.hasher.Sum(nil))
135+
digest = NewDigest(d.hasher.Sum(nil))
113136
d.hasher.Reset()
114137
return
115138
}
@@ -121,12 +144,12 @@ func (d *sqlDigester) doNormalize(sql string) (result string) {
121144
return
122145
}
123146

124-
func (d *sqlDigester) doNormalizeDigest(sql string) (normalized, digest string) {
147+
func (d *sqlDigester) doNormalizeDigest(sql string) (normalized string, digest *Digest) {
125148
d.normalize(sql)
126149
normalized = d.buffer.String()
127150
d.hasher.Write(d.buffer.Bytes())
128151
d.buffer.Reset()
129-
digest = fmt.Sprintf("%x", d.hasher.Sum(nil))
152+
digest = NewDigest(d.hasher.Sum(nil))
130153
d.hasher.Reset()
131154
return
132155
}

digester_test.go

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
package parser_test
1515

1616
import (
17+
"crypto/sha256"
18+
"encoding/hex"
19+
"fmt"
20+
"testing"
21+
1722
. "github.com/pingcap/check"
1823
"github.com/pingcap/parser"
1924
)
@@ -71,7 +76,7 @@ func (s *testSQLDigestSuite) TestNormalize(c *C) {
7176

7277
normalized2, digest2 := parser.NormalizeDigest(test.input)
7378
c.Assert(normalized2, Equals, normalized)
74-
c.Assert(digest2, Equals, digest, Commentf("%+v", test))
79+
c.Assert(digest2.String(), Equals, digest.String(), Commentf("%+v", test))
7580
}
7681
}
7782

@@ -86,12 +91,12 @@ func (s *testSQLDigestSuite) TestNormalizeDigest(c *C) {
8691
for _, test := range tests {
8792
normalized, digest := parser.NormalizeDigest(test.sql)
8893
c.Assert(normalized, Equals, test.normalized)
89-
c.Assert(digest, Equals, test.digest)
94+
c.Assert(digest.String(), Equals, test.digest)
9095

9196
normalized = parser.Normalize(test.sql)
9297
digest = parser.DigestNormalized(normalized)
9398
c.Assert(normalized, Equals, test.normalized)
94-
c.Assert(digest, Equals, test.digest)
99+
c.Assert(digest.String(), Equals, test.digest)
95100
}
96101
}
97102

@@ -106,10 +111,10 @@ func (s *testSQLDigestSuite) TestDigestHashEqForSimpleSQL(c *C) {
106111
for _, sql := range sqlGroup {
107112
dig := parser.DigestHash(sql)
108113
if d == "" {
109-
d = dig
114+
d = dig.String()
110115
continue
111116
}
112-
c.Assert(d, Equals, dig)
117+
c.Assert(d, Equals, dig.String())
113118
}
114119
}
115120
}
@@ -123,10 +128,42 @@ func (s *testSQLDigestSuite) TestDigestHashNotEqForSimpleSQL(c *C) {
123128
for _, sql := range sqlGroup {
124129
dig := parser.DigestHash(sql)
125130
if d == "" {
126-
d = dig
131+
d = dig.String()
127132
continue
128133
}
129-
c.Assert(d, Not(Equals), dig)
134+
c.Assert(d, Not(Equals), dig.String())
130135
}
131136
}
132137
}
138+
139+
func (s *testSQLDigestSuite) TestGenDigest(c *C) {
140+
hash := genRandDigest("abc")
141+
digest := parser.NewDigest(hash)
142+
c.Assert(digest.String(), Equals, fmt.Sprintf("%x", hash))
143+
c.Assert(digest.Bytes(), DeepEquals, hash)
144+
digest = parser.NewDigest(nil)
145+
c.Assert(digest.String(), Equals, "")
146+
c.Assert(digest.Bytes(), IsNil)
147+
}
148+
149+
func genRandDigest(str string) []byte {
150+
hasher := sha256.New()
151+
hasher.Write([]byte(str))
152+
return hasher.Sum(nil)
153+
}
154+
155+
func BenchmarkDigestHexEncode(b *testing.B) {
156+
digest1 := genRandDigest("abc")
157+
b.ResetTimer()
158+
for i := 0; i < b.N; i++ {
159+
hex.EncodeToString(digest1)
160+
}
161+
}
162+
163+
func BenchmarkDigestSprintf(b *testing.B) {
164+
digest1 := genRandDigest("abc")
165+
b.ResetTimer()
166+
for i := 0; i < b.N; i++ {
167+
fmt.Sprintf("%x", digest1)
168+
}
169+
}

0 commit comments

Comments
 (0)