Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion dm/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ func (c *Checker) Init(ctx context.Context) (err error) {
c.checkList = append(c.checkList, checker.NewTargetPrivilegeChecker(
c.instances[0].targetDB.DB,
c.instances[0].targetDBInfo,
c.instances[0].targetDB.Version,
))
}
// sourceID -> DB
Expand Down Expand Up @@ -334,6 +335,7 @@ func (c *Checker) Init(ctx context.Context) (err error) {
c.checkList = append(c.checkList, checker.NewSourceDumpPrivilegeChecker(
instance.sourceDB.DB,
instance.sourceDBinfo,
instance.sourceDB.Version,
info.sourceID2SourceTables[sourceID],
exportCfg.Consistency,
c.dumpWholeInstance,
Expand Down Expand Up @@ -364,7 +366,7 @@ func (c *Checker) Init(ctx context.Context) (err error) {
c.checkList = append(c.checkList, checker.NewMySQLBinlogRowImageChecker(instance.sourceDB.DB, instance.sourceDBinfo))
}
if _, ok := c.checkingItems[config.ReplicationPrivilegeChecking]; ok {
c.checkList = append(c.checkList, checker.NewSourceReplicationPrivilegeChecker(instance.sourceDB.DB, instance.sourceDBinfo))
c.checkList = append(c.checkList, checker.NewSourceReplicationPrivilegeChecker(instance.sourceDB.DB, instance.sourceDBinfo, instance.sourceDB.Version))
}
if _, ok := c.checkingItems[config.OnlineDDLChecking]; c.onlineDDL != nil && ok {
c.checkList = append(c.checkList, checker.NewOnlineDDLChecker(instance.sourceDB.DB, info.sourceID2InterestedDB[i], c.onlineDDL, instance.baList))
Expand Down
2 changes: 1 addition & 1 deletion dm/pkg/checker/conn_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (c *connNumberChecker) check(ctx context.Context, checkerName string, neede
markCheckError(result, err)
return result
}
err2 := verifyPrivilegesWithResult(result, grants, neededPriv)
err2 := verifyPrivilegesWithResult(result, grants, neededPriv, c.toCheckDB.Version)
if err2 != nil {
// no enough privilege to check the user's connection number
result.State = StateWarning
Expand Down
37 changes: 25 additions & 12 deletions dm/pkg/checker/privilege.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ type SourceDumpPrivilegeChecker struct {
checkTables []filter.Table
consistency string
dumpWholeInstance bool
version string
}

// NewSourceDumpPrivilegeChecker returns a RealChecker.
func NewSourceDumpPrivilegeChecker(
db *sql.DB,
dbinfo *dbutil.DBConfig,
version string,
checkTables []filter.Table,
consistency string,
dumpWholeInstance bool,
Expand All @@ -70,6 +72,7 @@ func NewSourceDumpPrivilegeChecker(
checkTables: checkTables,
consistency: consistency,
dumpWholeInstance: dumpWholeInstance,
version: version,
}
}

Expand Down Expand Up @@ -107,7 +110,7 @@ func (pc *SourceDumpPrivilegeChecker) Check(ctx context.Context) *Result {
dumpRequiredPrivs[mysql.LockTablesPriv] = priv{needGlobal: true}
}

err2 := verifyPrivilegesWithResult(result, grants, dumpRequiredPrivs)
err2 := verifyPrivilegesWithResult(result, grants, dumpRequiredPrivs, pc.version)
if err2 != nil {
result.Errors = append(result.Errors, err2)
result.Instruction = "Please grant the required privileges to the account."
Expand All @@ -126,13 +129,14 @@ func (pc *SourceDumpPrivilegeChecker) Name() string {

// SourceReplicatePrivilegeChecker checks replication privileges of source DB.
type SourceReplicatePrivilegeChecker struct {
db *sql.DB
dbinfo *dbutil.DBConfig
db *sql.DB
dbinfo *dbutil.DBConfig
version string
}

// NewSourceReplicationPrivilegeChecker returns a RealChecker.
func NewSourceReplicationPrivilegeChecker(db *sql.DB, dbinfo *dbutil.DBConfig) RealChecker {
return &SourceReplicatePrivilegeChecker{db: db, dbinfo: dbinfo}
func NewSourceReplicationPrivilegeChecker(db *sql.DB, dbinfo *dbutil.DBConfig, version string) RealChecker {
return &SourceReplicatePrivilegeChecker{db: db, dbinfo: dbinfo, version: version}
}

// Check implements the RealChecker interface.
Expand All @@ -154,7 +158,7 @@ func (pc *SourceReplicatePrivilegeChecker) Check(ctx context.Context) *Result {
mysql.ReplicationSlavePriv: {needGlobal: true},
mysql.ReplicationClientPriv: {needGlobal: true},
}
err2 := verifyPrivilegesWithResult(result, grants, replRequiredPrivs)
err2 := verifyPrivilegesWithResult(result, grants, replRequiredPrivs, pc.version)
if err2 != nil {
result.Errors = append(result.Errors, err2)
result.State = StateFailure
Expand All @@ -169,12 +173,13 @@ func (pc *SourceReplicatePrivilegeChecker) Name() string {
}

type TargetPrivilegeChecker struct {
db *sql.DB
dbinfo *dbutil.DBConfig
db *sql.DB
dbinfo *dbutil.DBConfig
version string
}

func NewTargetPrivilegeChecker(db *sql.DB, dbinfo *dbutil.DBConfig) RealChecker {
return &TargetPrivilegeChecker{db: db, dbinfo: dbinfo}
func NewTargetPrivilegeChecker(db *sql.DB, dbinfo *dbutil.DBConfig, version string) RealChecker {
return &TargetPrivilegeChecker{db: db, dbinfo: dbinfo, version: version}
}

func (t *TargetPrivilegeChecker) Name() string {
Expand Down Expand Up @@ -203,7 +208,7 @@ func (t *TargetPrivilegeChecker) Check(ctx context.Context) *Result {
mysql.DropPriv: {needGlobal: true},
mysql.IndexPriv: {needGlobal: true},
}
err2 := verifyPrivilegesWithResult(result, grants, replRequiredPrivs)
err2 := verifyPrivilegesWithResult(result, grants, replRequiredPrivs, t.version)
if err2 != nil {
result.Errors = append(result.Errors, err2)
// because we cannot be very precisely sure about which table
Expand All @@ -217,8 +222,9 @@ func verifyPrivilegesWithResult(
result *Result,
grants []string,
requiredPriv map[mysql.PrivilegeType]priv,
version string,
) *Error {
lackedPriv, err := VerifyPrivileges(grants, requiredPriv)
lackedPriv, err := VerifyPrivileges(grants, requiredPriv, version)
if err != nil {
// nolint
return NewError("%s", err.Error())
Expand Down Expand Up @@ -284,12 +290,19 @@ func LackedPrivilegesAsStr(lackPriv map[mysql.PrivilegeType]priv) string {
func VerifyPrivileges(
grants []string,
lackPrivs map[mysql.PrivilegeType]priv,
version string,
) (map[mysql.PrivilegeType]priv, error) {
if len(grants) == 0 {
return nil, errors.New("there is no such grant defined for current user on host '%%'")
}

p := parser.New()

// Support for BINLOG MONITOR and other MariaDB things
if strings.Contains(version, "MariaDB") {
p.SetMariaDB(true)
}

for _, grant := range grants {
if len(lackPrivs) == 0 {
break
Expand Down
8 changes: 4 additions & 4 deletions dm/pkg/checker/privilege_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func TestVerifyDumpPrivileges(t *testing.T) {
if cs.dumpWholeInstance {
dumpRequiredPrivs[mysql.SelectPriv] = priv{needGlobal: true}
}
err := verifyPrivilegesWithResult(result, cs.grants, dumpRequiredPrivs)
err := verifyPrivilegesWithResult(result, cs.grants, dumpRequiredPrivs, "8.0.11")
if cs.dumpState == StateSuccess {
require.Nil(t, err, "grants: %v", cs.grants)
} else {
Expand Down Expand Up @@ -325,7 +325,7 @@ func TestVerifyReplicationPrivileges(t *testing.T) {
mysql.ReplicationSlavePriv: {needGlobal: true},
mysql.ReplicationClientPriv: {needGlobal: true},
}
err := verifyPrivilegesWithResult(result, cs.grants, replRequiredPrivs)
err := verifyPrivilegesWithResult(result, cs.grants, replRequiredPrivs, "8.0.11")
if cs.replicationState == StateSuccess {
require.Nil(t, err, "grants: %v", cs.grants)
} else {
Expand Down Expand Up @@ -405,7 +405,7 @@ func TestVerifyPrivilegesWildcard(t *testing.T) {
dbs: genTableLevelPrivs(cs.checkTables),
},
}
err := verifyPrivilegesWithResult(result, cs.grants, requiredPrivs)
err := verifyPrivilegesWithResult(result, cs.grants, requiredPrivs, "8.0.11")
if cs.replicationState == StateSuccess {
require.Nil(t, err, "grants: %v", cs.grants)
} else {
Expand Down Expand Up @@ -469,7 +469,7 @@ func TestVerifyTargetPrivilege(t *testing.T) {
mysql.AlterPriv: {needGlobal: true},
mysql.DropPriv: {needGlobal: true},
}
err := verifyPrivilegesWithResult(result, cs.grants, replRequiredPrivs)
err := verifyPrivilegesWithResult(result, cs.grants, replRequiredPrivs, "8.0.11")
if cs.checkState == StateSuccess {
require.Nil(t, err, "grants: %v", cs.grants)
} else {
Expand Down
10 changes: 5 additions & 5 deletions dm/pkg/conn/basedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ type BaseDB struct {
doNotClose bool

// SELECT VERSION()
version string
Version string
}

// NewBaseDB returns *BaseDB object for test.
Expand All @@ -213,7 +213,7 @@ func NewBaseDB(db *sql.DB, scope terror.ErrScope, version string, doFuncInClose
Retry: &retry.FiniteRetryStrategy{},
Scope: scope,
doFuncInClose: doFuncInClose,
version: version,
Version: version,
}
}

Expand All @@ -238,7 +238,7 @@ func NewBaseDBForTestWithVersion(db *sql.DB, version string, doFuncInClose ...fu
Retry: &retry.FiniteRetryStrategy{},
Scope: terror.ScopeNotSet,
doFuncInClose: doFuncInClose,
version: version,
Version: version,
}
}

Expand Down Expand Up @@ -398,15 +398,15 @@ func (d *BaseDB) needsModernTerminology() bool {
// - https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/show/show-replica-hosts
//
// Old syntax is still accepted.
if strings.Contains(d.version, "MariaDB") {
if strings.Contains(d.Version, "MariaDB") {
return false
}

// https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html#mysqld-8-4-0-deprecation-removal
// MySQL 8.4 removed `SHOW MASTER STATUS`.
minVer := semver.New("8.4.0")

v, err := semver.NewVersion(d.version)
v, err := semver.NewVersion(d.Version)
if err != nil {
return false
}
Expand Down
4 changes: 2 additions & 2 deletions dm/pkg/conn/basedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestNeedsModernTerminology(t *testing.T) {
}

for _, tc := range cases {
b.version = tc.version
require.Equal(t, tc.modern, b.needsModernTerminology(), b.version)
b.Version = tc.version
require.Equal(t, tc.modern, b.needsModernTerminology(), b.Version)
}
}