Updates migrations to check collation/charset before trying to fix it (#4325)
* Updates migrations to check collation/charset before trying to fix it * Update server/services/store/sqlstore/data_migrations.go Co-authored-by: Doug Lauder <wiggin77@warpmail.net> Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> Co-authored-by: Doug Lauder <wiggin77@warpmail.net>
This commit is contained in:
parent
5d82fb8181
commit
f2d98f940f
1 changed files with 29 additions and 8 deletions
|
@ -663,7 +663,7 @@ func (s *SQLStore) RunFixCollationsAndCharsetsMigration() error {
|
||||||
collation = "utf8mb4_general_ci"
|
collation = "utf8mb4_general_ci"
|
||||||
charSet = "utf8mb4"
|
charSet = "utf8mb4"
|
||||||
} else {
|
} else {
|
||||||
collation, charSet, err = s.getCollationAndCharset()
|
collation, charSet, err = s.getCollationAndCharset("Channels")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -677,8 +677,27 @@ func (s *SQLStore) RunFixCollationsAndCharsetsMigration() error {
|
||||||
|
|
||||||
merr := merror.New()
|
merr := merror.New()
|
||||||
|
|
||||||
// alter each table; this is idempotent
|
// alter each table if there is a collation or charset mismatch
|
||||||
for _, name := range tableNames {
|
for _, name := range tableNames {
|
||||||
|
tableCollation, tableCharSet, err := s.getCollationAndCharset(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if collation == tableCollation && charSet == tableCharSet {
|
||||||
|
// nothing to do
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Warn(
|
||||||
|
"found collation/charset mismatch, fixing table",
|
||||||
|
mlog.String("tableName", name),
|
||||||
|
mlog.String("tableCollation", tableCollation),
|
||||||
|
mlog.String("tableCharSet", tableCharSet),
|
||||||
|
mlog.String("collation", collation),
|
||||||
|
mlog.String("charSet", charSet),
|
||||||
|
)
|
||||||
|
|
||||||
sql := fmt.Sprintf("ALTER TABLE %s CONVERT TO CHARACTER SET '%s' COLLATE '%s'", name, charSet, collation)
|
sql := fmt.Sprintf("ALTER TABLE %s CONVERT TO CHARACTER SET '%s' COLLATE '%s'", name, charSet, collation)
|
||||||
result, err := s.db.Exec(sql)
|
result, err := s.db.Exec(sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -731,7 +750,7 @@ func (s *SQLStore) getFocalBoardTableNames() ([]string, error) {
|
||||||
return names, nil
|
return names, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLStore) getCollationAndCharset() (string, string, error) {
|
func (s *SQLStore) getCollationAndCharset(tableName string) (string, string, error) {
|
||||||
if s.dbType != model.MysqlDBType {
|
if s.dbType != model.MysqlDBType {
|
||||||
return "", "", newErrInvalidDBType("getCollationAndCharset requires MySQL")
|
return "", "", newErrInvalidDBType("getCollationAndCharset requires MySQL")
|
||||||
}
|
}
|
||||||
|
@ -739,7 +758,7 @@ func (s *SQLStore) getCollationAndCharset() (string, string, error) {
|
||||||
query := s.getQueryBuilder(s.db).
|
query := s.getQueryBuilder(s.db).
|
||||||
Select("table_collation").
|
Select("table_collation").
|
||||||
From("information_schema.tables").
|
From("information_schema.tables").
|
||||||
Where(sq.Eq{"table_name": "Channels"}).
|
Where(sq.Eq{"table_name": tableName}).
|
||||||
Where("table_schema=(SELECT DATABASE())")
|
Where("table_schema=(SELECT DATABASE())")
|
||||||
|
|
||||||
row := query.QueryRow()
|
row := query.QueryRow()
|
||||||
|
@ -747,17 +766,19 @@ func (s *SQLStore) getCollationAndCharset() (string, string, error) {
|
||||||
var collation string
|
var collation string
|
||||||
err := row.Scan(&collation)
|
err := row.Scan(&collation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("error fetching collation: %w", err)
|
return "", "", fmt.Errorf("error fetching collation for table %s: %w", tableName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// obtains the charset from the first column that has it set
|
||||||
query = s.getQueryBuilder(s.db).
|
query = s.getQueryBuilder(s.db).
|
||||||
Select("CHARACTER_SET_NAME").
|
Select("CHARACTER_SET_NAME").
|
||||||
From("information_schema.columns").
|
From("information_schema.columns").
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"table_name": "Channels",
|
"table_name": tableName,
|
||||||
"COLUMN_NAME": "Name",
|
|
||||||
}).
|
}).
|
||||||
Where("table_schema=(SELECT DATABASE())")
|
Where("table_schema=(SELECT DATABASE())").
|
||||||
|
Where(sq.NotEq{"CHARACTER_SET_NAME": "NULL"}).
|
||||||
|
Limit(1)
|
||||||
|
|
||||||
row = query.QueryRow()
|
row = query.QueryRow()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue