diff --git a/common/config_test.go b/common/config_test.go index ac8679198fcca9d5ecba72ef99a9f45bfed660e5..60b7719db89ff1422449005c6a70be198463eb3b 100644 --- a/common/config_test.go +++ b/common/config_test.go @@ -90,18 +90,20 @@ func TestParseDSN(t *testing.T) { // go-sql-driver dsn "user@unix(/path/to/socket)/dbname", "root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local", - "user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true", + "user:password@tcp(localhost:5555)/dbname?tls=skip-verify", + "user:password@tcp(localhost:5555)/dbname?autocommit=true", "user:password@/dbname?sql_mode=TRADITIONAL", - "user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci", + "user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s", + "user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?collation=utf8mb4_unicode_ci", "id:password@tcp(your-amazonaws-uri.com:3306)/dbname", "user@cloudsql(project-id:instance-name)/dbname", "user@cloudsql(project-id:regionname:instance-name)/dbname", - "user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped", + //"user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped", multi key in map, pretty print in random order, by pass + "user:password@tcp/dbname?sys_var=esc%40ped", "user:password@/dbname", "user:password@/", - "user:password@tcp(localhost:3307)/database?charset=utf8&timeout=5s", + "user:password@tcp(localhost:3307)/database?timeout=5s", } - err := GoldenDiff(func() { for _, dsn := range dsns { pretty.Println(dsn) diff --git a/common/testdata/TestParseDSN.golden b/common/testdata/TestParseDSN.golden index a03cc825facf5d18ceacfcaacfeddb6f8d258221..39f4e8973280d353f6504bafc458a5edecd23364 100644 --- a/common/testdata/TestParseDSN.golden +++ b/common/testdata/TestParseDSN.golden @@ -438,7 +438,7 @@ root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local Disable: false, Version: 99999, } -user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true +user:password@tcp(localhost:5555)/dbname?tls=skip-verify &common.Dsn{ User: "user", Password: "password", @@ -451,6 +451,28 @@ user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true TLS: "skip-verify", ServerPubKey: "", MaxAllowedPacket: 4194304, + Params: {}, + Timeout: "0s", + ReadTimeout: "0s", + WriteTimeout: "0s", + AllowNativePasswords: true, + AllowOldPasswords: false, + Disable: false, + Version: 99999, +} +user:password@tcp(localhost:5555)/dbname?autocommit=true +&common.Dsn{ + User: "user", + Password: "password", + Net: "tcp", + Addr: "localhost:5555", + Schema: "dbname", + Charset: "utf8", + Collation: "utf8_general_ci", + Loc: "UTC", + TLS: "", + ServerPubKey: "", + MaxAllowedPacket: 4194304, Params: {"autocommit":"true"}, Timeout: "0s", ReadTimeout: "0s", @@ -482,7 +504,7 @@ user:password@/dbname?sql_mode=TRADITIONAL Disable: false, Version: 99999, } -user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci +user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s &common.Dsn{ User: "user", Password: "password", @@ -490,7 +512,7 @@ user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_ Addr: "[de:ad:be:ef::ca:fe]:80", Schema: "dbname", Charset: "utf8", - Collation: "utf8mb4_unicode_ci", + Collation: "utf8_general_ci", Loc: "UTC", TLS: "", ServerPubKey: "", @@ -504,6 +526,28 @@ user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_ Disable: false, Version: 99999, } +user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?collation=utf8mb4_unicode_ci +&common.Dsn{ + User: "user", + Password: "password", + Net: "tcp", + Addr: "[de:ad:be:ef::ca:fe]:80", + Schema: "dbname", + Charset: "utf8", + Collation: "utf8mb4_unicode_ci", + Loc: "UTC", + TLS: "", + ServerPubKey: "", + MaxAllowedPacket: 4194304, + Params: {}, + Timeout: "0s", + ReadTimeout: "0s", + WriteTimeout: "0s", + AllowNativePasswords: true, + AllowOldPasswords: false, + Disable: false, + Version: 99999, +} id:password@tcp(your-amazonaws-uri.com:3306)/dbname &common.Dsn{ User: "id", @@ -570,20 +614,20 @@ user@cloudsql(project-id:regionname:instance-name)/dbname Disable: false, Version: 99999, } -user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped +user:password@tcp/dbname?sys_var=esc%40ped &common.Dsn{ User: "user", Password: "password", Net: "tcp", Addr: "127.0.0.1:3306", Schema: "dbname", - Charset: "utf8mb4,utf8", + Charset: "utf8", Collation: "utf8_general_ci", Loc: "UTC", TLS: "", ServerPubKey: "", MaxAllowedPacket: 4194304, - Params: {"charset":"utf8mb4,utf8", "sys_var":"esc@ped"}, + Params: {"sys_var":"esc@ped"}, Timeout: "0s", ReadTimeout: "0s", WriteTimeout: "0s", @@ -636,7 +680,7 @@ user:password@/ Disable: false, Version: 99999, } -user:password@tcp(localhost:3307)/database?charset=utf8&timeout=5s +user:password@tcp(localhost:3307)/database?timeout=5s &common.Dsn{ User: "user", Password: "password", @@ -649,7 +693,7 @@ user:password@tcp(localhost:3307)/database?charset=utf8&timeout=5s TLS: "", ServerPubKey: "", MaxAllowedPacket: 4194304, - Params: {"charset":"utf8"}, + Params: {}, Timeout: "5s", ReadTimeout: "0s", WriteTimeout: "0s", diff --git a/database/mysql.go b/database/mysql.go index 9c699a7f2ca405b0c4d7bbafb0e8b8c6177b1fa9..5000c74dd099f153c86415ac16f916ff69c34f58 100644 --- a/database/mysql.go +++ b/database/mysql.go @@ -189,11 +189,14 @@ func (db *Connector) ColumnCardinality(tb, col string) float64 { common.Log.Debug("(db *Connector) ColumnCardinality() No table status: %s", tb) return 1 } - rowTotal := tbStatus.Rows[0].Rows - if rowTotal == 0 { + rowTotal, err := strconv.ParseUint(string(tbStatus.Rows[0].Rows), 10, 64) + if rowTotal == 0 || err != nil { if common.Config.Sampling { common.Log.Debug("ColumnCardinality, %s rowTotal == 0", tb) } + if err != nil { + common.Log.Error("ColumnCardinality, Error:", err.Error()) + } return 1 } diff --git a/database/sampling.go b/database/sampling.go index 896c264c68356dba88266b38d584ecbc757b53e7..eb7c45c47125b945e399ef76bb20a3738c058d55 100644 --- a/database/sampling.go +++ b/database/sampling.go @@ -19,6 +19,7 @@ package database import ( "database/sql" "fmt" + "strconv" "strings" "time" @@ -74,9 +75,12 @@ func (db *Connector) SamplingData(onlineConn *Connector, tables ...string) error return nil } - tableRows := tableStatus.Rows[0].Rows - if tableRows == 0 { + tableRows, err := strconv.ParseUint(string(tableStatus.Rows[0].Rows), 10, 64) + if tableRows == 0 || err != nil { common.Log.Info("SamplingData, Table %s with no data, stop sampling", table) + if err != nil { + common.Log.Error("SamplingData, Error: ", err.Error()) + } return nil } diff --git a/database/show.go b/database/show.go index b81605e5e831285b9a0a50ab5c687f62baa1778c..bb571680b93fe8786a8464d55cf887c845edbd1c 100644 --- a/database/show.go +++ b/database/show.go @@ -41,25 +41,25 @@ type tableStatusRow struct { Engine []byte // 该表使用的存储引擎 Version []byte // 该表的 .frm 文件版本号 RowFormat []byte // 该表使用的行存储格式 - Rows uint64 // 表行数, InnoDB 引擎中为预估值,甚至可能会有40%~50%的数值偏差 - AvgRowLength uint64 // 平均行长度 + Rows []byte // 表行数, InnoDB 引擎中为预估值,甚至可能会有40%~50%的数值偏差 + AvgRowLength []byte // 平均行长度 // MyISAM: Data_length 为数据文件的大小,单位为 bytes // InnoDB: Data_length 为聚簇索引分配的近似内存量,单位为 bytes, 计算方式为聚簇索引数量乘以 InnoDB 页面大小 // 其他不同的存储引擎中该值的意义可能不尽相同 - DataLength uint64 + DataLength []byte // MyISAM: Max_data_length 为数据文件长度的最大值。这是在给定使用的数据指针大小的情况下,可以存储在表中的数据的最大字节数 // InnoDB: 未使用 // 其他不同的存储引擎中该值的意义可能不尽相同 - MaxDataLength uint64 + MaxDataLength []byte // MyISAM: Index_length 为 index 文件的大小,单位为 bytes // InnoDB: Index_length 为非聚簇索引分配的近似内存量,单位为 bytes,计算方式为非聚簇索引数量乘以 InnoDB 页面大小 // 其他不同的存储引擎中该值的意义可能不尽相同 - IndexLength uint64 + IndexLength []byte - DataFree uint64 // 已分配但未使用的字节数 + DataFree []byte // 已分配但未使用的字节数 AutoIncrement []byte // 下一个自增值 CreateTime []byte // 创建时间 UpdateTime []byte // 最近一次更新时间,该值不准确 diff --git a/database/show_test.go b/database/show_test.go index 6355dc4b3194f9a3ddc58d9bf324beec87465202..00a42b7f4870250a16c6adf7db8dced9f9e45fb5 100644 --- a/database/show_test.go +++ b/database/show_test.go @@ -38,16 +38,15 @@ func TestShowTableStatus(t *testing.T) { } pretty.Println(ts) - // FIXME: too much column NULL ABLE - //connTest.Database = "sakila" - //ts, err = connTest.ShowTableStatus("actor_info") - //if err != nil { - // t.Error("ShowTableStatus Error: ", err) - //} - //if string(ts.Rows[0].Comment) != "VIEW" { - // t.Error("actor_info should be VIEW", ts.Rows[0].Comment) - //} - //pretty.Println(ts) + connTest.Database = "sakila" + ts, err = connTest.ShowTableStatus("actor_info") + if err != nil { + t.Error("ShowTableStatus Error: ", err) + } + if string(ts.Rows[0].Comment) != "VIEW" { + t.Error("actor_info should be VIEW", ts.Rows[0].Comment) + } + pretty.Println(ts) connTest.Database = orgDatabase common.Log.Debug("Exiting function: %s", common.GetFunctionName()) } diff --git a/env/env_test.go b/env/env_test.go index a719564d3bd409e0c1ed2dfe576f44f97e908aa1..f10eaab60be1171afb103707f9057b8b2a433d91 100644 --- a/env/env_test.go +++ b/env/env_test.go @@ -259,14 +259,13 @@ func TestCreateTable(t *testing.T) { "rental", "staff", "store", - // FIXME: SUPPORT VIEW - //"staff_list", - //"customer_list", - //"actor_info", - //"sales_by_film_category", - //"sales_by_store", - //"nicer_but_slower_film_list", - //"film_list", + "staff_list", + "customer_list", + "actor_info", + "sales_by_film_category", + "sales_by_store", + "nicer_but_slower_film_list", + "film_list", } for _, table := range tables { err := vEnv.createTable(rEnv, table)