From 66df5dc9ca39360f7258ada76d065f1f9ad50545 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Sat, 12 Jul 2025 17:54:07 +0800 Subject: [PATCH] fix: force mysql connection charset utf8mb4 --- util/netutils/ipv6_test.go | 30 ++++++++++++++++++++++ utils/misc.go | 52 +++++++++++++++++++++++++------------- utils/misc_test.go | 6 ++--- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/util/netutils/ipv6_test.go b/util/netutils/ipv6_test.go index ff18914..176fc29 100644 --- a/util/netutils/ipv6_test.go +++ b/util/netutils/ipv6_test.go @@ -737,6 +737,10 @@ func TestMac2LinkLocal(t *testing.T) { mac: "00:00:00:00:00:00", linkLocal: "fe80::200:ff:fe00:0", }, + { + mac: "14:09:dc:cf:16:d5", + linkLocal: "fe80::1609:dcff:fecf:16d5", + }, } for _, c := range cases { v6, err := Mac2LinkLocal(c.mac) @@ -747,3 +751,29 @@ func TestMac2LinkLocal(t *testing.T) { } } } + +func TestIPV6ToNetIP(t *testing.T) { + cases := []struct { + ipv6 string + }{ + { + ipv6: "fd:3ffe:3200:2::1", + }, + { + ipv6: "::", + }, + { + ipv6: "::1", + }, + { + ipv6: "::ffff:ffff:ffff:ffff", + }, + } + for _, c := range cases { + ipv6, _ := NewIPV6Addr(c.ipv6) + netIP := ipv6.ToIP() + if netIP.String() != ipv6.String() { + t.Errorf("IPv6 %s to netIP got %s want %s", c.ipv6, netIP.String(), ipv6.String()) + } + } +} diff --git a/utils/misc.go b/utils/misc.go index 69232c2..72d5cb1 100644 --- a/utils/misc.go +++ b/utils/misc.go @@ -24,6 +24,8 @@ import ( "strconv" "strings" "time" + + "yunion.io/x/pkg/errors" ) type selectFunc func(obj interface{}) (string, error) @@ -535,6 +537,31 @@ func GetSizeKB(sizeStr, defaultSize string) (int64, error) { return bytes / 1024, nil } +func transMysqlQuery(dburl string) (string, error) { + queryPos := strings.IndexByte(dburl, '?') + if queryPos == 0 { + return "", fmt.Errorf("Missing database name") + } + var query url.Values + if queryPos > 0 { + queryStr := dburl[queryPos+1:] + if len(queryStr) > 0 { + var err error + query, err = url.ParseQuery(queryStr) + if err != nil { + return "", errors.Wrap(err, "ParseQuery") + } + } + dburl = dburl[:queryPos] + } else { + query = url.Values{} + } + query.Set("parseTime", "true") + query.Set("charset", "utf8mb4") + query.Set("interpolateParams", "true") + return dburl + "?" + query.Encode(), nil +} + func TransSQLAchemyURL(pySQLSrc string) (dialect, ret string, err error) { if len(pySQLSrc) == 0 { err = fmt.Errorf("Empty input") @@ -543,6 +570,10 @@ func TransSQLAchemyURL(pySQLSrc string) (dialect, ret string, err error) { dialect = "mysql" if !strings.Contains(pySQLSrc, `//`) { + pySQLSrc, err = transMysqlQuery(pySQLSrc) + if err != nil { + return + } return dialect, pySQLSrc, nil } @@ -560,26 +591,11 @@ func TransSQLAchemyURL(pySQLSrc string) (dialect, ret string, err error) { return } user, passwd, host, port, dburl := strs[1], strs[2], strs[3], strs[4], strs[5] - queryPos := strings.IndexByte(dburl, '?') - if queryPos == 0 { - err = fmt.Errorf("Missing database name") + dburl, err = transMysqlQuery(dburl) + if err != nil { return } - var query url.Values - if queryPos > 0 { - queryStr := dburl[queryPos+1:] - if len(queryStr) > 0 { - query, err = url.ParseQuery(queryStr) - if err != nil { - return - } - } - dburl = dburl[:queryPos] - } else { - query = url.Values{} - } - query.Set("parseTime", "True") - ret = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", user, passwd, host, port, dburl, query.Encode()) + ret = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", user, passwd, host, port, dburl) return } diff --git a/utils/misc_test.go b/utils/misc_test.go index c1d6744..4cdaf74 100644 --- a/utils/misc_test.go +++ b/utils/misc_test.go @@ -661,18 +661,18 @@ func TestTransSQLAchemyURL(t *testing.T) { { name: "should convert", args: args{"mysql+pymysql://root:root@127.0.0.1:3306/mclouds?charset=utf8"}, - wantRet: "root:root@tcp(127.0.0.1:3306)/mclouds?charset=utf8&parseTime=True", + wantRet: "root:root@tcp(127.0.0.1:3306)/mclouds?charset=utf8mb4&interpolateParams=true&parseTime=true", wantErr: false, }, { name: "bare", args: args{"root:root@127.0.0.1:3306/mclouds?charset=utf8"}, - wantRet: "root:root@127.0.0.1:3306/mclouds?charset=utf8", + wantRet: "root:root@127.0.0.1:3306/mclouds?charset=utf8mb4&interpolateParams=true&parseTime=true", wantErr: false, }, { name: "supported at", args: args{"mysql+pymysql://root:5bTcx^@Peh4nj3H7@127.0.0.1:3306/mclouds?charset=utf8"}, - wantRet: "root:5bTcx^@Peh4nj3H7@tcp(127.0.0.1:3306)/mclouds?charset=utf8&parseTime=True", + wantRet: "root:5bTcx^@Peh4nj3H7@tcp(127.0.0.1:3306)/mclouds?charset=utf8mb4&interpolateParams=true&parseTime=true", wantErr: false, }, }