AutoMigrate recreates table with composite unique index even if the model has not changed

Aperta
#171 0 commenti 2 reazioni 1 assegnatario Vedi su GitHub

@jinzhu ci sta già lavorando.

Dal 11/11/2023.

Valutazione

Questa issue non è ancora stata valutata.

Descrizione

GORM Playground Link

https://github.com/go-gorm/playground/pull/660

Description

I'm using the GORM ORM framework for Golang and have encountered an issue with composite unique indexes. When using the following structure that includes a composite unique index, I noticed that the recreateTable process (which includes creating a temporary table, migrating data, deleting the old table, and renaming the table) is executed every time AutoMigrate is called, even if the model has not changed.

type Gateway struct {
  IP string    `gorm:"index:uniq_vip,unique"`
  UIN string `gorm:"index:uniq_vip,unique"`
}

However, there is no issue when using a single-field unique index like the following model:

type Gateway struct {
  IP string    `gorm:"index:uniq_vip,unique"`
  UIN string 
}

After investigating, I found that the alterColumn = true is set in the code at https://github.com/go-gorm/gorm/blob/v1.25.5/migrator/migrator.go#L500, because field.Unique is false while unique is true.

	// check unique
	if unique, ok := columnType.Unique(); ok && unique != field.Unique {
		// not primary key
		if !field.PrimaryKey {
			alterColumn = true
		}
	}

Further investigation revealed that the problematic code for the sqlite-driver is at https://github.com/go-gorm/sqlite/blob/v1.5.4/ddlmod.go#L165:

for _, column := range getAllColumns(matches[1]) {
				for idx, c := range result.columns {
					if c.NameValue.String == column {
						c.UniqueValue = sql.NullBool{Bool: strings.ToUpper(strings.Fields(str)[1]) == "UNIQUE", Valid: true}
						result.columns[idx] = c
					}
				}
			}

Since it is a composite unique index, getAllColumns(matches[1]) returns a length of 2, containing the column names IP and UIN. Neither of these individual fields is unique, but they form a composite unique index. The condition strings.Fields(str)[1]) == "UNIQUE" is not strict enough, causing each field to be set as unique.

I expect the check should be something like strings.Fields(str)[1]) == "UNIQUE" && len(getAllColumns(matches[1])) == 1, so that the unique attribute is only set for fields when there is only one field in the unique index, rather than setting unique for each field in the composite unique index. After modifying the condition and testing, the behavior is as expected.

Lingua principale
Go
Stelle
235
Fork
217
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di go-gorm/sqlite

Tutte le issue di go-gorm/sqlite

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.