2019-06-08 16:53:45 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-06-08 16:53:45 +03:00
2021-09-19 14:49:59 +03:00
package db
2019-06-08 16:53:45 +03:00
2019-08-24 12:24:45 +03:00
import (
"fmt"
2022-01-02 16:12:35 +03:00
"strconv"
2019-08-24 12:24:45 +03:00
2022-01-02 16:12:35 +03:00
"code.gitea.io/gitea/modules/log"
2019-08-24 12:24:45 +03:00
"code.gitea.io/gitea/modules/setting"
2021-06-30 00:00:02 +03:00
2022-01-02 16:12:35 +03:00
"xorm.io/xorm"
2021-06-30 00:00:02 +03:00
"xorm.io/xorm/schemas"
2019-08-24 12:24:45 +03:00
)
2019-06-08 16:53:45 +03:00
2024-01-10 14:03:23 +03:00
// ConvertDatabaseTable converts database and tables from utf8 to utf8mb4 if it's mysql and set ROW_FORMAT=dynamic
func ConvertDatabaseTable ( ) error {
2021-06-30 00:00:02 +03:00
if x . Dialect ( ) . URI ( ) . DBType != schemas . MYSQL {
return nil
}
2024-01-10 14:03:23 +03:00
r , err := CheckCollations ( x )
if err != nil {
return err
}
_ , err = x . Exec ( fmt . Sprintf ( "ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE %s" , setting . Database . Name , r . ExpectedCollation ) )
2019-06-08 16:53:45 +03:00
if err != nil {
return err
}
tables , err := x . DBMetas ( )
if err != nil {
return err
}
for _ , table := range tables {
2024-01-10 14:03:23 +03:00
if _ , err := x . Exec ( fmt . Sprintf ( "ALTER TABLE `%s` ROW_FORMAT=dynamic" , table . Name ) ) ; err != nil {
2020-09-11 11:25:06 +03:00
return err
}
2024-01-10 14:03:23 +03:00
if _ , err := x . Exec ( fmt . Sprintf ( "ALTER TABLE `%s` CONVERT TO CHARACTER SET utf8mb4 COLLATE %s" , table . Name , r . ExpectedCollation ) ) ; err != nil {
2019-06-08 16:53:45 +03:00
return err
}
}
return nil
}
2022-01-02 16:12:35 +03:00
2023-04-17 16:22:10 +03:00
// ConvertVarcharToNVarchar converts database and tables from varchar to nvarchar if it's mssql
func ConvertVarcharToNVarchar ( ) error {
if x . Dialect ( ) . URI ( ) . DBType != schemas . MSSQL {
return nil
}
sess := x . NewSession ( )
defer sess . Close ( )
res , err := sess . QuerySliceString ( ` SELECT ' ALTER TABLE ' + OBJECT_NAME ( SC . object_id ) + ' MODIFY SC . name NVARCHAR ( ' + CONVERT ( VARCHAR ( 5 ) , SC . max_length ) + ')'
FROM SYS . columns SC
JOIN SYS . types ST
ON SC . system_type_id = ST . system_type_id
AND SC . user_type_id = ST . user_type_id
WHERE ST . name = ' varchar ' ` )
if err != nil {
return err
}
for _ , row := range res {
if len ( row ) == 1 {
if _ , err = sess . Exec ( row [ 0 ] ) ; err != nil {
return err
}
}
}
return err
}
2022-01-02 16:12:35 +03:00
// Cell2Int64 converts a xorm.Cell type to int64,
// and handles possible irregular cases.
func Cell2Int64 ( val xorm . Cell ) int64 {
switch ( * val ) . ( type ) {
case [ ] uint8 :
log . Trace ( "Cell2Int64 ([]uint8): %v" , * val )
v , _ := strconv . ParseInt ( string ( ( * val ) . ( [ ] uint8 ) ) , 10 , 64 )
return v
}
return ( * val ) . ( int64 )
}