diff --git a/cluster/srv.go b/cluster/srv.go index 7f4e2e7f3..61590b66a 100644 --- a/cluster/srv.go +++ b/cluster/srv.go @@ -226,7 +226,7 @@ func (cluster *Cluster) newServerMonitor(url string, user string, pass string, c server.Domain = domain server.TLSConfigUsed = ConstTLSCurrentConfig server.ClusterGroup = cluster - server.DBVersion = dbhelper.NewMySQLVersion("Unknowed-0.0.0", "") + server.DBVersion, _ = dbhelper.NewMySQLVersion("Unknowed-0.0.0", "") server.Name, server.Port, server.PostgressDB = misc.SplitHostPortDB(url) server.ServiceName = cluster.Name + "/svc/" + server.Name server.IsGroupReplicationSlave = false diff --git a/utils/dbhelper/dbhelper.go b/utils/dbhelper/dbhelper.go index adb4c816a..5040ee590 100644 --- a/utils/dbhelper/dbhelper.go +++ b/utils/dbhelper/dbhelper.go @@ -668,7 +668,7 @@ func ChangeMaster(db *sqlx.DB, opt ChangeMasterOpt, myver *MySQLVersion) (string case "SLAVE_POS": cm += ", " + masterOrSource + "_USE_GTID=SLAVE_POS" case "CURRENT_POS": - if myver.Greater(*NewMySQLVersion("10.10.0", "")) && myver.IsMariaDB() { + if myver.Greater("10.10.0") && myver.IsMariaDB() { cm += ", " + masterOrSource + "_USE_GTID=SLAVE_POS, MASTER_DEMOTE_TO_SLAVE=1" } else { cm += ", " + masterOrSource + "_USE_GTID=CURRENT_POS" @@ -734,12 +734,13 @@ func GetDBVersion(db *sqlx.DB) (*MySQLVersion, string, error) { if err != nil { return &MySQLVersion{}, stmt, err } - v := NewMySQLVersion(version, "") + v, _ := NewMySQLVersion(version, "") if !v.IsPPostgreSQL() { stmt = "SELECT @@version_comment" db.QueryRowx(stmt).Scan(&versionComment) } - return NewMySQLVersion(version, versionComment), stmt, nil + nv, _ := NewMySQLVersion(version, versionComment) + return nv, stmt, nil } // Unused does not look like safe way or documenting it @@ -2682,9 +2683,7 @@ func BenchCleanup(db *sqlx.DB) error { func AnalyzeTable(db *sqlx.DB, myver *MySQLVersion, table string) (string, error) { query := "ANALYZE TABLE " + table - var v *MySQLVersion - v = NewMySQLVersion("10.4.0", "") - if myver.Greater(*v) && myver.IsMariaDB() { + if myver.Greater("10.4.0") && myver.IsMariaDB() { query += " PERSISTENT FOR ALL" } _, err := db.Exec(query) diff --git a/utils/dbhelper/version.go b/utils/dbhelper/version.go index cc2acf96c..67172c5ee 100644 --- a/utils/dbhelper/version.go +++ b/utils/dbhelper/version.go @@ -13,8 +13,6 @@ import ( "fmt" "strconv" "strings" - - version "github.com/mcuadros/go-version" ) type MySQLVersion struct { @@ -24,11 +22,15 @@ type MySQLVersion struct { Release int `json:"release"` } -func NewMySQLVersion(version string, versionComment string) *MySQLVersion { +/* +Create new MySQLVersion object from string +*/ +func NewMySQLVersion(version string, versionComment string) (*MySQLVersion, int) { + var tokens []string mv := new(MySQLVersion) - if strings.Contains(version, "MariaDB") { + if strings.Contains(version, "MariaDB") || strings.Contains(versionComment, "MariaDB") { mv.Flavor = "MariaDB" - } else if strings.Contains(version, "PostgreSQL") { + } else if strings.Contains(version, "PostgreSQL") || strings.Contains(versionComment, "PostgreSQL") { mv.Flavor = "PostgreSQL" } else if strings.Contains(versionComment, "Percona") { mv.Flavor = "Percona" @@ -38,38 +40,73 @@ func NewMySQLVersion(version string, versionComment string) *MySQLVersion { if mv.Flavor == "PostgreSQL" { infos := strings.Split(version, " ") version = infos[1] - tokens := strings.Split(version, ".") + tokens = strings.Split(version, ".") mv.Major, _ = strconv.Atoi(tokens[0]) - mv.Minor, _ = strconv.Atoi(tokens[1]) + if len(tokens) >= 2 { + mv.Minor, _ = strconv.Atoi(tokens[1]) + } + if len(tokens) >= 3 { + mv.Release, _ = strconv.Atoi(tokens[2]) + } } else { infos := strings.Split(version, "-") version = infos[0] - tokens := strings.Split(version, ".") + tokens = strings.Split(version, ".") + mv.Major, _ = strconv.Atoi(tokens[0]) if len(tokens) >= 2 { - mv.Major, _ = strconv.Atoi(tokens[0]) mv.Minor, _ = strconv.Atoi(tokens[1]) + } + if len(tokens) >= 3 { mv.Release, _ = strconv.Atoi(tokens[2]) } } - return mv + return mv, len(tokens) } -func (mv *MySQLVersion) Between(Min MySQLVersion, Max MySQLVersion) bool { - ver := "1" + fmt.Sprintf("%03d", mv.Major) + fmt.Sprintf("%03d", mv.Minor) + fmt.Sprintf("%03d", mv.Release) - ver_min := "1" + fmt.Sprintf("%03d", Min.Major) + fmt.Sprintf("%03d", Min.Minor) + fmt.Sprintf("%03d", Min.Release) - ver_max := "1" + fmt.Sprintf("%03d", Max.Major) + fmt.Sprintf("%03d", Max.Minor) + fmt.Sprintf("%03d", Max.Release) - sup := version.Compare(ver, ver_min, ">") - inf := version.Compare(ver_max, ver, ">") - if sup && inf { - return true +func (mv *MySQLVersion) ToInt(tokens int) int { + //Major + if tokens == 1 { + return mv.Major * 1000000 } - return false + //Minor + if tokens == 2 { + return (mv.Major * 1000000) + (mv.Minor * 1000) + } + + return (mv.Major * 1000000) + (mv.Minor * 1000) + mv.Release +} + +func (mv *MySQLVersion) ToString() string { + return fmt.Sprintf("%d.%d.%d", mv.Major, mv.Minor, mv.Release) +} + +func (mv *MySQLVersion) Greater(vstring string) bool { + v, tokens := NewMySQLVersion(vstring, mv.Flavor) + return mv.ToInt(tokens) > v.ToInt(tokens) +} + +func (mv *MySQLVersion) GreaterEqual(vstring string) bool { + v, tokens := NewMySQLVersion(vstring, mv.Flavor) + return mv.ToInt(tokens) >= v.ToInt(tokens) +} + +func (mv *MySQLVersion) Lower(vstring string) bool { + v, tokens := NewMySQLVersion(vstring, mv.Flavor) + return mv.ToInt(tokens) < v.ToInt(tokens) +} + +func (mv *MySQLVersion) LowerEqual(vstring string) bool { + v, tokens := NewMySQLVersion(vstring, mv.Flavor) + return mv.ToInt(tokens) <= v.ToInt(tokens) +} + +func (mv *MySQLVersion) Equal(vstring string) bool { + v, tokens := NewMySQLVersion(vstring, mv.Flavor) + return mv.ToInt(tokens) == v.ToInt(tokens) } -func (mv *MySQLVersion) Greater(Min MySQLVersion) bool { - ver := "1" + fmt.Sprintf("%03d", mv.Major) + fmt.Sprintf("%03d", mv.Minor) + fmt.Sprintf("%03d", mv.Release) - ver_min := "1" + fmt.Sprintf("%03d", Min.Major) + fmt.Sprintf("%03d", Min.Minor) + fmt.Sprintf("%03d", Min.Release) - return version.Compare(ver, ver_min, ">") +func (mv *MySQLVersion) Between(minvstring string, maxvstring string) bool { + return mv.GreaterEqual(minvstring) && mv.LowerEqual(maxvstring) } func (mv *MySQLVersion) IsMySQL() bool { diff --git a/utils/dbhelper/version_test.go b/utils/dbhelper/version_test.go new file mode 100644 index 000000000..17743e9b9 --- /dev/null +++ b/utils/dbhelper/version_test.go @@ -0,0 +1,248 @@ +// replication-manager - Replication Manager Monitoring and CLI for MariaDB and MySQL +// Copyright 2017-2021 SIGNAL18 CLOUD SAS +// Authors: Guillaume Lefranc +// Stephane Varoqui +// This source code is licensed under the GNU General Public License, version 3. +// Redistribution/Reuse of this code is permitted under the GNU v3 license, as +// an additional term, ALL code must carry the original Author(s) credit in comment form. +// See LICENSE in this directory for the integral text. + +package dbhelper + +import ( + "testing" +) + +func TestMySQLVersion(t *testing.T) { + var tstring, cstring string + tstring, cstring = "8.0.28", "" + mv, _ := NewMySQLVersion(tstring, cstring) + + t.Logf("Created Version of %s with version %s", mv.Flavor, mv.ToString()) + + if mv.Equal("8.0.28") { + t.Log("Equal(8.0.28) is true (Correct)") + } else { + t.Error("Equal(8.0.28) is false (Incorrect)") + } + + if mv.Equal("8.0") { + t.Log("Equal(8.0) is true (correct)") + } else { + t.Error("Equal(8.0) is false (Incorrect)") + } + + if mv.Equal("8") { + t.Log("Equal(8) is true (correct)") + } else { + t.Error("Equal(8) is false (Incorrect)") + } + + if mv.Equal("10") == false { + t.Log("Equal(10) is false (correct)") + } else { + t.Error("Equal(10) is true (Incorrect)") + } + + if mv.GreaterEqual("8.0.28") { + t.Log("GreaterEqual(8.0.28) is true (Correct)") + } else { + t.Error("GreaterEqual(8.0.28) is false (Incorrect)") + } + + if mv.GreaterEqual("8.0") { + t.Log("GreaterEqual(8.0) is true (Correct)") + } else { + t.Error("GreaterEqual(8.0) is false (Incorrect)") + } + + if mv.GreaterEqual("8.1") == false { + t.Log("GreaterEqual(8.1) is false (Correct)") + } else { + t.Error("GreaterEqual(8.0) is true (Incorrect)") + } + + if mv.Greater("8.1") == false { + t.Log("GreaterEqual(8.1) is false (Correct)") + } else { + t.Error("GreaterEqual(8.1) is true (Incorrect)") + } + + if mv.Greater("8") == false { + t.Log("Greater(8) is false (Correct)") + } else { + t.Error("Greater(8) is true (Incorrect)") + } + + if mv.Greater("5") { + t.Log("Greater(5) is true (Correct)") + } else { + t.Error("Greater(5) is false (Incorrect)") + } + + if mv.LowerEqual("8.0.28") { + t.Log("LowerEqual(8.0.28) is true (Correct)") + } else { + t.Error("LowerEqual(8.0.28) is false (Incorrect)") + } + + if mv.LowerEqual("8.0") { + t.Log("LowerEqual(8.0) is true (Correct)") + } else { + t.Error("LowerEqual(8.0) is false (Incorrect)") + } + + if mv.LowerEqual("8.1") { + t.Log("LowerEqual(8.1) is true (Correct)") + } else { + t.Error("LowerEqual(8.0) is false (Incorrect)") + } + + if mv.Lower("8.1") { + t.Log("Lower(8.1) is true (Correct)") + } else { + t.Error("Lower(8.1) is false (Incorrect)") + } + + if mv.Lower("8") == false { + t.Log("Lower(8) is false (Correct)") + } else { + t.Error("Lower(8) is true (Incorrect)") + } + + if mv.Lower("5") == false { + t.Log("Lower(5) is false (Correct)") + } else { + t.Error("Lower(5) is true (Incorrect)") + } + + if mv.Between("5", "8") { + t.Log("Between(5,8) is true (Correct)") + } else { + t.Error("Between(5,8) is false (Incorrect)") + } + + if mv.Between("10", "11") == false { + t.Log("Between(10,11) is false (Correct)") + } else { + t.Error("Between(10,11) is true (Incorrect)") + } + +} + +func TestMariaDBVersion(t *testing.T) { + var tstring, cstring string + tstring, cstring = "10.11.6-MariaDB-1:10.11.6+maria~ubu2204-log", "MariaDB" + mv, _ := NewMySQLVersion(tstring, cstring) + + t.Logf("Created Version of %s with version %s", mv.Flavor, mv.ToString()) + + if mv.Equal(mv.ToString()) { + t.Log("Equal(mv.ToString()) is true (Correct)") + } else { + t.Error("Equal(mv.ToString()) is false (Incorrect)") + } + + if mv.Equal("10.11") { + t.Log("Equal(10.11) is true (correct)") + } else { + t.Error("Equal(10.11) is false (Incorrect)") + } + + if mv.Equal("10") { + t.Log("Equal(10) is true (correct)") + } else { + t.Error("Equal(10) is false (Incorrect)") + } + + if mv.Equal("8") == false { + t.Log("Equal(8) is false (correct)") + } else { + t.Error("Equal(8) is true (Incorrect)") + } + + if mv.GreaterEqual("10.11.6") { + t.Log("GreaterEqual(10.11.6) is true (Correct)") + } else { + t.Error("GreaterEqual(10.11.6) is false (Incorrect)") + } + + if mv.GreaterEqual("10.11") { + t.Log("GreaterEqual(10.11) is true (Correct)") + } else { + t.Error("GreaterEqual(10.11) is false (Incorrect)") + } + + if mv.GreaterEqual("10.12") == false { + t.Log("GreaterEqual(10.12) is false (Correct)") + } else { + t.Error("GreaterEqual(10.12) is true (Incorrect)") + } + + if mv.Greater("10.12") == false { + t.Log("GreaterEqual(10.12) is false (Correct)") + } else { + t.Error("GreaterEqual(10.12) is true (Incorrect)") + } + + if mv.Greater("10") == false { + t.Log("Greater(10) is false (Correct)") + } else { + t.Error("Greater(10) is true (Incorrect)") + } + + if mv.Greater("5") { + t.Log("Greater(5) is true (Correct)") + } else { + t.Error("Greater(5) is false (Incorrect)") + } + + if mv.LowerEqual("10.11.6") { + t.Log("LowerEqual(10.11.6) is true (Correct)") + } else { + t.Error("LowerEqual(10.11.6) is false (Incorrect)") + } + + if mv.LowerEqual("10.11") { + t.Log("LowerEqual(10.11) is true (Correct)") + } else { + t.Error("LowerEqual(10.11) is false (Incorrect)") + } + + if mv.LowerEqual("10.12") { + t.Log("LowerEqual(10.12) is true (Correct)") + } else { + t.Error("LowerEqual(10.12) is false (Incorrect)") + } + + if mv.Lower("10.12") { + t.Log("Lower(10.12) is true (Correct)") + } else { + t.Error("Lower(10.12) is false (Incorrect)") + } + + if mv.Lower("10") == false { + t.Log("Lower(10) is false (Correct)") + } else { + t.Error("Lower(10) is true (Incorrect)") + } + + if mv.Lower("5") == false { + t.Log("Lower(5) is false (Correct)") + } else { + t.Error("Lower(5) is true (Incorrect)") + } + + if mv.Between("5", "10") { + t.Log("Between(5,10) is true (Correct)") + } else { + t.Error("Between(5,10) is false (Incorrect)") + } + + if mv.Between("5", "8") == false { + t.Log("Between(5,8) is false (Correct)") + } else { + t.Error("Between(5,8) is true (Incorrect)") + } + +}