Skip to content

Commit

Permalink
privilege/privileges: sort in-memory db privilege table records (#37688)
Browse files Browse the repository at this point in the history
close #37488
  • Loading branch information
tiancaiamao authored Sep 19, 2022
1 parent b5ed674 commit a6db4b7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
31 changes: 15 additions & 16 deletions privilege/privileges/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"encoding/json"
"fmt"
"net"
"sort"
"strings"
"sync/atomic"
"time"
Expand Down Expand Up @@ -429,16 +428,7 @@ func (p *MySQLPrivilege) buildUserMap() {
p.UserMap = userMap
}

type sortedUserRecord []UserRecord

func (s sortedUserRecord) Len() int {
return len(s)
}

func (s sortedUserRecord) Less(i, j int) bool {
x := s[i]
y := s[j]

func compareBaseRecord(x, y *baseRecord) bool {
// Compare two item by user's host first.
c1 := compareHost(x.Host, y.Host)
if c1 < 0 {
Expand All @@ -452,6 +442,10 @@ func (s sortedUserRecord) Less(i, j int) bool {
return x.User < y.User
}

func compareUserRecord(x, y UserRecord) bool {
return compareBaseRecord(&x.baseRecord, &y.baseRecord)
}

// compareHost compares two host string using some special rules, return value 1, 0, -1 means > = <.
// TODO: Check how MySQL do it exactly, instead of guess its rules.
func compareHost(x, y string) int {
Expand Down Expand Up @@ -501,13 +495,9 @@ func compareHost(x, y string) int {
return 0
}

func (s sortedUserRecord) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

// SortUserTable sorts p.User in the MySQLPrivilege struct.
func (p MySQLPrivilege) SortUserTable() {
sort.Sort(sortedUserRecord(p.User))
slices.SortFunc(p.User, compareUserRecord)
}

// LoadGlobalPrivTable loads the mysql.global_priv table from database.
Expand All @@ -530,11 +520,20 @@ func (p *MySQLPrivilege) LoadDBTable(ctx sessionctx.Context) error {
return nil
}

func compareDBRecord(x, y dbRecord) bool {
return compareBaseRecord(&x.baseRecord, &y.baseRecord)
}

func (p *MySQLPrivilege) buildDBMap() {
dbMap := make(map[string][]dbRecord, len(p.DB))
for _, record := range p.DB {
dbMap[record.User] = append(dbMap[record.User], record)
}

// Sort the records to make the matching rule work.
for _, records := range dbMap {
slices.SortFunc(records, compareDBRecord)
}
p.DBMap = dbMap
}

Expand Down
14 changes: 14 additions & 0 deletions privilege/privileges/privileges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2949,3 +2949,17 @@ func TestCheckPreparePrivileges(t *testing.T) {
}()
tk2.ResultSetToResult(rs, "").Check(testkit.Rows("1"))
}

func TestIssue37488(t *testing.T) {
store := createStoreAndPrepareDB(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE USER dba_test@'%';")
tk.MustExec("GRANT SELECT,INSERT,UPDATE,DELETE ON test.* TO 'dba_test'@'%';")
tk.MustExec("CREATE USER dba_test@'192.168.%';")
tk.MustExec("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER ON test.* TO 'dba_test'@'192.168.%';")

require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "dba_test", Hostname: "192.168.13.15"}, nil, nil))
tk.MustQuery("select current_user()").Check(testkit.Rows("dba_test@192.168.%"))
tk.MustExec("DROP TABLE IF EXISTS a;") // succ
}

0 comments on commit a6db4b7

Please sign in to comment.