code.gitea.io/gitea@v1.21.7/models/migrations/v1_13/v145.go (about)

     1  // Copyright 2020 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package v1_13 //nolint
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"code.gitea.io/gitea/modules/setting"
    10  
    11  	"xorm.io/xorm"
    12  )
    13  
    14  func IncreaseLanguageField(x *xorm.Engine) error {
    15  	type LanguageStat struct {
    16  		RepoID   int64  `xorm:"UNIQUE(s) INDEX NOT NULL"`
    17  		Language string `xorm:"VARCHAR(50) UNIQUE(s) INDEX NOT NULL"`
    18  	}
    19  
    20  	if err := x.Sync(new(LanguageStat)); err != nil {
    21  		return err
    22  	}
    23  
    24  	if setting.Database.Type.IsSQLite3() {
    25  		// SQLite maps VARCHAR to TEXT without size so we're done
    26  		return nil
    27  	}
    28  
    29  	// need to get the correct type for the new column
    30  	inferredTable, err := x.TableInfo(new(LanguageStat))
    31  	if err != nil {
    32  		return err
    33  	}
    34  	column := inferredTable.GetColumn("language")
    35  	sqlType := x.Dialect().SQLType(column)
    36  
    37  	sess := x.NewSession()
    38  	defer sess.Close()
    39  	if err := sess.Begin(); err != nil {
    40  		return err
    41  	}
    42  
    43  	switch {
    44  	case setting.Database.Type.IsMySQL():
    45  		if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat MODIFY COLUMN language %s", sqlType)); err != nil {
    46  			return err
    47  		}
    48  	case setting.Database.Type.IsMSSQL():
    49  		// Yet again MSSQL just has to be awkward.
    50  		// Here we have to drop the constraints first and then rebuild them
    51  		constraints := make([]string, 0)
    52  		if err := sess.SQL(`SELECT i.name AS Name
    53  			FROM sys.indexes i INNER JOIN sys.index_columns ic
    54        			ON i.index_id = ic.index_id AND i.object_id = ic.object_id
    55     			INNER JOIN sys.tables AS t
    56        			ON t.object_id = i.object_id
    57  			INNER JOIN sys.columns c
    58  				ON t.object_id = c.object_id AND ic.column_id = c.column_id
    59  			WHERE t.name = 'language_stat' AND c.name = 'language'`).Find(&constraints); err != nil {
    60  			return fmt.Errorf("Find constraints: %w", err)
    61  		}
    62  		for _, constraint := range constraints {
    63  			if _, err := sess.Exec(fmt.Sprintf("DROP INDEX [%s] ON `language_stat`", constraint)); err != nil {
    64  				return fmt.Errorf("Drop table `language_stat` constraint `%s`: %w", constraint, err)
    65  			}
    66  		}
    67  		if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat ALTER COLUMN language %s", sqlType)); err != nil {
    68  			return err
    69  		}
    70  		// Finally restore the constraint
    71  		if err := sess.CreateUniques(new(LanguageStat)); err != nil {
    72  			return err
    73  		}
    74  	case setting.Database.Type.IsPostgreSQL():
    75  		if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat ALTER COLUMN language TYPE %s", sqlType)); err != nil {
    76  			return err
    77  		}
    78  	}
    79  
    80  	return sess.Commit()
    81  }