From 932e9afef9c108db68db1fa8ddef729756e3e9c7 Mon Sep 17 00:00:00 2001 From: zakaria chahboun Date: Wed, 31 Aug 2022 05:56:55 +0100 Subject: [PATCH 1/6] ignore generated columns when recreateTable --- ddlmod.go | 22 ++++++++++++++++++++++ ddlmod_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ migrator.go | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/ddlmod.go b/ddlmod.go index c8db01f..bcd87e2 100644 --- a/ddlmod.go +++ b/ddlmod.go @@ -229,3 +229,25 @@ func (d *ddl) getColumns() []string { } return res } + +func (d *ddl) getSafeColumns() []string { + res := []string{} + + for _, f := range d.fields { + fUpper := strings.ToUpper(f) + if strings.HasPrefix(fUpper, "PRIMARY KEY") || + strings.HasPrefix(fUpper, "CHECK") || + strings.HasPrefix(fUpper, "CONSTRAINT") || + strings.Contains(fUpper, "GENERATED ALWAYS AS") { + continue + } + + reg := regexp.MustCompile("^[\"`']?([\\w\\d]+)[\"`']?") + match := reg.FindStringSubmatch(f) + + if match != nil { + res = append(res, "`"+match[1]+"`") + } + } + return res +} \ No newline at end of file diff --git a/ddlmod_test.go b/ddlmod_test.go index 5e7a840..dc51db6 100644 --- a/ddlmod_test.go +++ b/ddlmod_test.go @@ -227,3 +227,46 @@ func TestGetColumns(t *testing.T) { }) } } + +func TestGetSafeColumns(t *testing.T) { + params := []struct { + name string + ddl string + columns []string + }{ + { + name: "with_fk", + ddl: "CREATE TABLE `notes` (`id` integer NOT NULL,`text` varchar(500),`user_id` integer,PRIMARY KEY (`id`),CONSTRAINT `fk_users_notes` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`))", + columns: []string{"`id`", "`text`", "`user_id`"}, + }, + { + name: "with_check", + ddl: "CREATE TABLE Persons (ID int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Age int,CHECK (Age>=18),CHECK (FirstName!='John'))", + columns: []string{"`ID`", "`LastName`", "`FirstName`", "`Age`"}, + }, + { + name: "with_escaped_quote", + ddl: "CREATE TABLE Persons (ID int NOT NULL,LastName varchar(255) NOT NULL DEFAULT \"\",FirstName varchar(255))", + columns: []string{"`ID`", "`LastName`", "`FirstName`"}, + }, + { + name: "with_generated_column", + ddl: "CREATE TABLE Persons (ID int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),FullName varchar(255) GENERATED ALWAYS AS (FirstName || ' ' || LastName))", + columns: []string{"`ID`", "`LastName`", "`FirstName`"}, + }, + } + + for _, p := range params { + t.Run(p.name, func(t *testing.T) { + testDDL, err := parseDDL(p.ddl) + if err != nil { + panic(err.Error()) + } + + cols := testDDL.getSafeColumns() + + tests.AssertEqual(t, p.columns, cols) + }) + } +} + diff --git a/migrator.go b/migrator.go index 9d11cfc..a57548e 100644 --- a/migrator.go +++ b/migrator.go @@ -400,7 +400,7 @@ func (m Migrator) recreateTable(value interface{}, tablePtr *string, if err != nil { return err } - columns := createDDL.getColumns() + columns := createDDL.getSafeColumns() return m.DB.Transaction(func(tx *gorm.DB) error { if err := tx.Exec(createSQL, sqlArgs...).Error; err != nil { From 65fe63a6e2eef84c5342395347d464285290274e Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Sat, 8 Oct 2022 10:59:41 +0800 Subject: [PATCH 2/6] Update ddlmod_test.go --- ddlmod_test.go | 44 +++----------------------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/ddlmod_test.go b/ddlmod_test.go index dc51db6..49d2ce4 100644 --- a/ddlmod_test.go +++ b/ddlmod_test.go @@ -37,9 +37,9 @@ func TestParseDDL(t *testing.T) { }, {"no brackets", []string{"create table test"}, 0, nil}, {"with_special_characters", []string{ - "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"测试,\")", + "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"ʵãËØïÔºå\")", }, 1, []migrator.ColumnType{ - {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "测试,", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, + {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "ʵãËØïÔºå", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, }, }, { @@ -192,43 +192,6 @@ func TestRemoveConstraint(t *testing.T) { } func TestGetColumns(t *testing.T) { - params := []struct { - name string - ddl string - columns []string - }{ - { - name: "with_fk", - ddl: "CREATE TABLE `notes` (`id` integer NOT NULL,`text` varchar(500),`user_id` integer,PRIMARY KEY (`id`),CONSTRAINT `fk_users_notes` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`))", - columns: []string{"`id`", "`text`", "`user_id`"}, - }, - { - name: "with_check", - ddl: "CREATE TABLE Persons (ID int NOT NULL,LastName varchar(255) NOT NULL,FirstName varchar(255),Age int,CHECK (Age>=18),CHECK (FirstName!='John'))", - columns: []string{"`ID`", "`LastName`", "`FirstName`", "`Age`"}, - }, - { - name: "with_escaped_quote", - ddl: "CREATE TABLE Persons (ID int NOT NULL,LastName varchar(255) NOT NULL DEFAULT \"\",FirstName varchar(255))", - columns: []string{"`ID`", "`LastName`", "`FirstName`"}, - }, - } - - for _, p := range params { - t.Run(p.name, func(t *testing.T) { - testDDL, err := parseDDL(p.ddl) - if err != nil { - panic(err.Error()) - } - - cols := testDDL.getColumns() - - tests.AssertEqual(t, p.columns, cols) - }) - } -} - -func TestGetSafeColumns(t *testing.T) { params := []struct { name string ddl string @@ -263,10 +226,9 @@ func TestGetSafeColumns(t *testing.T) { panic(err.Error()) } - cols := testDDL.getSafeColumns() + cols := testDDL.getColumns() tests.AssertEqual(t, p.columns, cols) }) } } - From c2488049bbee083153eaff25cfb5d31d6e8d6f22 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Sat, 8 Oct 2022 11:00:10 +0800 Subject: [PATCH 3/6] Update ddlmod.go --- ddlmod.go | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/ddlmod.go b/ddlmod.go index bcd87e2..cc593b1 100644 --- a/ddlmod.go +++ b/ddlmod.go @@ -212,27 +212,6 @@ func (d *ddl) hasConstraint(name string) bool { func (d *ddl) getColumns() []string { res := []string{} - for _, f := range d.fields { - fUpper := strings.ToUpper(f) - if strings.HasPrefix(fUpper, "PRIMARY KEY") || - strings.HasPrefix(fUpper, "CHECK") || - strings.HasPrefix(fUpper, "CONSTRAINT") { - continue - } - - reg := regexp.MustCompile("^[\"`']?([\\w\\d]+)[\"`']?") - match := reg.FindStringSubmatch(f) - - if match != nil { - res = append(res, "`"+match[1]+"`") - } - } - return res -} - -func (d *ddl) getSafeColumns() []string { - res := []string{} - for _, f := range d.fields { fUpper := strings.ToUpper(f) if strings.HasPrefix(fUpper, "PRIMARY KEY") || @@ -250,4 +229,4 @@ func (d *ddl) getSafeColumns() []string { } } return res -} \ No newline at end of file +} From 67eaab8a72fdc03dc9a1fbc45b1f62c4f3b3909f Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Sat, 8 Oct 2022 11:05:07 +0800 Subject: [PATCH 4/6] Update migrator.go --- migrator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrator.go b/migrator.go index a57548e..9d11cfc 100644 --- a/migrator.go +++ b/migrator.go @@ -400,7 +400,7 @@ func (m Migrator) recreateTable(value interface{}, tablePtr *string, if err != nil { return err } - columns := createDDL.getSafeColumns() + columns := createDDL.getColumns() return m.DB.Transaction(func(tx *gorm.DB) error { if err := tx.Exec(createSQL, sqlArgs...).Error; err != nil { From 6916d11d6ea646b7b2bcd0be1d7885b0e0fb2e2d Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Sat, 8 Oct 2022 11:06:48 +0800 Subject: [PATCH 5/6] Update ddlmod_test.go --- ddlmod_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddlmod_test.go b/ddlmod_test.go index 49d2ce4..84f6397 100644 --- a/ddlmod_test.go +++ b/ddlmod_test.go @@ -37,9 +37,9 @@ func TestParseDDL(t *testing.T) { }, {"no brackets", []string{"create table test"}, 0, nil}, {"with_special_characters", []string{ - "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"ʵãËØïÔºå\")", + "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"测试\")", }, 1, []migrator.ColumnType{ - {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "ʵãËØïÔºå", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, + {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "测试", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, }, }, { From 0c7fe2a392ac9f432e89ff506ff88a35f8998533 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Sat, 8 Oct 2022 11:08:08 +0800 Subject: [PATCH 6/6] Update ddlmod_test.go --- ddlmod_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddlmod_test.go b/ddlmod_test.go index 84f6397..88d0b35 100644 --- a/ddlmod_test.go +++ b/ddlmod_test.go @@ -37,9 +37,9 @@ func TestParseDDL(t *testing.T) { }, {"no brackets", []string{"create table test"}, 0, nil}, {"with_special_characters", []string{ - "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"测试\")", + "CREATE TABLE `test` (`text` varchar(10) DEFAULT \"测试, \")", }, 1, []migrator.ColumnType{ - {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "测试", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, + {NameValue: sql.NullString{String: "text", Valid: true}, DataTypeValue: sql.NullString{String: "varchar", Valid: true}, LengthValue: sql.NullInt64{Int64: 10, Valid: true}, ColumnTypeValue: sql.NullString{String: "varchar(10)", Valid: true}, DefaultValueValue: sql.NullString{String: "测试, ", Valid: true}, NullableValue: sql.NullBool{Valid: true}, UniqueValue: sql.NullBool{Valid: true}, PrimaryKeyValue: sql.NullBool{Valid: true}}, }, }, {