@@ -1890,3 +1890,114 @@ func TestMigrateWithUniqueIndexAndUnique(t *testing.T) {
18901890 }
18911891 }
18921892}
1893+
1894+ func testAutoMigrateDecimal (t * testing.T , model1 , model2 any ) []string {
1895+ tracer := Tracer {
1896+ Logger : DB .Config .Logger ,
1897+ Test : func (ctx context.Context , begin time.Time , fc func () (sql string , rowsAffected int64 ), err error ) {
1898+ sql , _ := fc ()
1899+ if strings .HasPrefix (sql , "ALTER TABLE " ) {
1900+ t .Fatalf ("shouldn't execute ALTER COLUMN TYPE if decimal is not change: sql: %s" , sql )
1901+ }
1902+ },
1903+ }
1904+ session := DB .Session (& gorm.Session {Logger : tracer })
1905+
1906+ DB .Migrator ().DropTable (model1 )
1907+ var modifySql []string
1908+ if err := session .AutoMigrate (model1 ); err != nil {
1909+ t .Fatalf ("failed to auto migrate, got error: %v" , err )
1910+ }
1911+ if err := session .AutoMigrate (model1 ); err != nil {
1912+ t .Fatalf ("failed to auto migrate, got error: %v" , err )
1913+ }
1914+ tracer2 := Tracer {
1915+ Logger : DB .Config .Logger ,
1916+ Test : func (ctx context.Context , begin time.Time , fc func () (sql string , rowsAffected int64 ), err error ) {
1917+ sql , _ := fc ()
1918+ modifySql = append (modifySql , sql )
1919+ },
1920+ }
1921+ session2 := DB .Session (& gorm.Session {Logger : tracer2 })
1922+ err := session2 .Table ("migrate_decimal_columns" ).Migrator ().AutoMigrate (model2 )
1923+ if err != nil {
1924+ t .Fatalf ("failed to get column types, got error: %v" , err )
1925+ }
1926+ return modifySql
1927+ }
1928+
1929+ func decimalColumnsTest [T , T2 any ](t * testing.T , expectedSql []string ) {
1930+ var t1 T
1931+ var t2 T2
1932+ modSql := testAutoMigrateDecimal (t , t1 , t2 )
1933+ var alterSQL []string
1934+ for _ , sql := range modSql {
1935+ if strings .HasPrefix (sql , "ALTER TABLE " ) {
1936+ alterSQL = append (alterSQL , sql )
1937+ }
1938+ }
1939+
1940+ if len (alterSQL ) != 3 {
1941+ t .Fatalf ("decimal changed error,expected: %+v,got: %+v." , expectedSql , alterSQL )
1942+ }
1943+ for i := range alterSQL {
1944+ if alterSQL [i ] != expectedSql [i ] {
1945+ t .Fatalf ("decimal changed error,expected: %+v,got: %+v." , expectedSql , alterSQL )
1946+ }
1947+ }
1948+ }
1949+
1950+ func TestAutoMigrateDecimal (t * testing.T ) {
1951+ if DB .Dialector .Name () == "sqlserver" { // database/sql will replace numeric to decimal. so only support decimal.
1952+ type MigrateDecimalColumn struct {
1953+ RecID1 int64 `gorm:"column:recid1;type:decimal(9,0);not null" json:"recid1"`
1954+ RecID2 int64 `gorm:"column:recid2;type:decimal(8);not null" json:"recid2"`
1955+ RecID3 int64 `gorm:"column:recid3;type:decimal(8,1);not null" json:"recid3"`
1956+ }
1957+ type MigrateDecimalColumn2 struct {
1958+ RecID1 int64 `gorm:"column:recid1;type:decimal(8);not null" json:"recid1"`
1959+ RecID2 int64 `gorm:"column:recid2;type:decimal(9,1);not null" json:"recid2"`
1960+ RecID3 int64 `gorm:"column:recid3;type:decimal(9,2);not null" json:"recid3"`
1961+ }
1962+ expectedSql := []string {
1963+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid1" decimal(8) NOT NULL` ,
1964+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid2" decimal(9,1) NOT NULL` ,
1965+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid3" decimal(9,2) NOT NULL` ,
1966+ }
1967+ decimalColumnsTest [MigrateDecimalColumn , MigrateDecimalColumn2 ](t , expectedSql )
1968+ } else if DB .Dialector .Name () == "postgres" {
1969+ type MigrateDecimalColumn struct {
1970+ RecID1 int64 `gorm:"column:recid1;type:numeric(9,0);not null" json:"recid1"`
1971+ RecID2 int64 `gorm:"column:recid2;type:numeric(8);not null" json:"recid2"`
1972+ RecID3 int64 `gorm:"column:recid3;type:numeric(8,1);not null" json:"recid3"`
1973+ }
1974+ type MigrateDecimalColumn2 struct {
1975+ RecID1 int64 `gorm:"column:recid1;type:numeric(8);not null" json:"recid1"`
1976+ RecID2 int64 `gorm:"column:recid2;type:numeric(9,1);not null" json:"recid2"`
1977+ RecID3 int64 `gorm:"column:recid3;type:numeric(9,2);not null" json:"recid3"`
1978+ }
1979+ expectedSql := []string {
1980+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid1" TYPE numeric(8) USING "recid1"::numeric(8)` ,
1981+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid2" TYPE numeric(9,1) USING "recid2"::numeric(9,1)` ,
1982+ `ALTER TABLE "migrate_decimal_columns" ALTER COLUMN "recid3" TYPE numeric(9,2) USING "recid3"::numeric(9,2)` ,
1983+ }
1984+ decimalColumnsTest [MigrateDecimalColumn , MigrateDecimalColumn2 ](t , expectedSql )
1985+ } else if DB .Dialector .Name () == "mysql" {
1986+ type MigrateDecimalColumn struct {
1987+ RecID1 int64 `gorm:"column:recid1;type:decimal(9,0);not null" json:"recid1"`
1988+ RecID2 int64 `gorm:"column:recid2;type:decimal(8);not null" json:"recid2"`
1989+ RecID3 int64 `gorm:"column:recid3;type:decimal(8,1);not null" json:"recid3"`
1990+ }
1991+ type MigrateDecimalColumn2 struct {
1992+ RecID1 int64 `gorm:"column:recid1;type:decimal(8);not null" json:"recid1"`
1993+ RecID2 int64 `gorm:"column:recid2;type:decimal(9,1);not null" json:"recid2"`
1994+ RecID3 int64 `gorm:"column:recid3;type:decimal(9,2);not null" json:"recid3"`
1995+ }
1996+ expectedSql := []string {
1997+ "ALTER TABLE `migrate_decimal_columns` MODIFY COLUMN `recid1` decimal(8) NOT NULL" ,
1998+ "ALTER TABLE `migrate_decimal_columns` MODIFY COLUMN `recid2` decimal(9,1) NOT NULL" ,
1999+ "ALTER TABLE `migrate_decimal_columns` MODIFY COLUMN `recid3` decimal(9,2) NOT NULL" ,
2000+ }
2001+ decimalColumnsTest [MigrateDecimalColumn , MigrateDecimalColumn2 ](t , expectedSql )
2002+ }
2003+ }
0 commit comments