From a870486c4f967d732b2786f320886b0230053c18 Mon Sep 17 00:00:00 2001 From: Walter Scheper Date: Mon, 9 Aug 2021 01:14:23 -0400 Subject: [PATCH 1/6] Do not emit ORDER BY for empty values (#4592) This restores the behavior from gorm v1, where calling `DB.Order` with an empty string, nil, or any unexpected type is a no-op. --- chainable_api.go | 14 ++++++++------ tests/query_test.go | 12 +++++++++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/chainable_api.go b/chainable_api.go index e17d9bb2..d5a0907d 100644 --- a/chainable_api.go +++ b/chainable_api.go @@ -209,12 +209,14 @@ func (db *DB) Order(value interface{}) (tx *DB) { tx.Statement.AddClause(clause.OrderBy{ Columns: []clause.OrderByColumn{v}, }) - default: - tx.Statement.AddClause(clause.OrderBy{ - Columns: []clause.OrderByColumn{{ - Column: clause.Column{Name: fmt.Sprint(value), Raw: true}, - }}, - }) + case string: + if v != "" { + tx.Statement.AddClause(clause.OrderBy{ + Columns: []clause.OrderByColumn{{ + Column: clause.Column{Name: v, Raw: true}, + }}, + }) + } } return } diff --git a/tests/query_test.go b/tests/query_test.go index 34999337..36046aee 100644 --- a/tests/query_test.go +++ b/tests/query_test.go @@ -842,7 +842,17 @@ func TestSearchWithEmptyChain(t *testing.T) { func TestOrder(t *testing.T) { dryDB := DB.Session(&gorm.Session{DryRun: true}) - result := dryDB.Order("age desc, name").Find(&User{}) + result := dryDB.Order("").Find(&User{}) + if !regexp.MustCompile("SELECT \\* FROM .*users.* IS NULL$").MatchString(result.Statement.SQL.String()) { + t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String()) + } + + result = dryDB.Order(nil).Find(&User{}) + if !regexp.MustCompile("SELECT \\* FROM .*users.* IS NULL$").MatchString(result.Statement.SQL.String()) { + t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String()) + } + + result = dryDB.Order("age desc, name").Find(&User{}) if !regexp.MustCompile("SELECT \\* FROM .*users.* ORDER BY age desc, name").MatchString(result.Statement.SQL.String()) { t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String()) } From cbe72751ac7e900a86ca843757c677b3c322732b Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 9 Aug 2021 07:16:25 +0200 Subject: [PATCH 2/6] Update Dependencies (#4582) * Create dependabot.yml * Bump reviewdog/action-golangci-lint from 1 to 2 (#1) Bumps [reviewdog/action-golangci-lint](https://github.com/reviewdog/action-golangci-lint) from 1 to 2. - [Release notes](https://github.com/reviewdog/action-golangci-lint/releases) - [Commits](https://github.com/reviewdog/action-golangci-lint/compare/v1...v2) --- updated-dependencies: - dependency-name: reviewdog/action-golangci-lint dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/stale from 3.0.7 to 4 (#2) Bumps [actions/stale](https://github.com/actions/stale) from 3.0.7 to 4. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v3.0.7...v4) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump gorm.io/gorm from 1.21.9 to 1.21.12 in /tests (#3) Bumps [gorm.io/gorm](https://github.com/go-gorm/gorm) from 1.21.9 to 1.21.12. - [Release notes](https://github.com/go-gorm/gorm/releases) - [Commits](https://github.com/go-gorm/gorm/compare/v1.21.9...v1.21.12) --- updated-dependencies: - dependency-name: gorm.io/gorm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump gorm.io/driver/mysql from 1.0.5 to 1.1.1 in /tests (#4) Bumps [gorm.io/driver/mysql](https://github.com/go-gorm/mysql) from 1.0.5 to 1.1.1. - [Release notes](https://github.com/go-gorm/mysql/releases) - [Commits](https://github.com/go-gorm/mysql/compare/v1.0.5...v1.1.1) --- updated-dependencies: - dependency-name: gorm.io/driver/mysql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/lib/pq from 1.6.0 to 1.10.2 in /tests (#5) Bumps [github.com/lib/pq](https://github.com/lib/pq) from 1.6.0 to 1.10.2. - [Release notes](https://github.com/lib/pq/releases) - [Commits](https://github.com/lib/pq/compare/v1.6.0...v1.10.2) --- updated-dependencies: - dependency-name: github.com/lib/pq dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/google/uuid from 1.2.0 to 1.3.0 in /tests (#6) Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.2.0 to 1.3.0. - [Release notes](https://github.com/google/uuid/releases) - [Commits](https://github.com/google/uuid/compare/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: github.com/google/uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/dependabot.yml | 15 +++++++++++++++ .github/workflows/invalid_question.yml | 2 +- .github/workflows/missing_playground.yml | 2 +- .github/workflows/reviewdog.yml | 2 +- .github/workflows/stale.yml | 2 +- tests/go.mod | 8 ++++---- 6 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e4e81074 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +--- +version: 2 +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: weekly + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + - package-ecosystem: gomod + directory: /tests + schedule: + interval: weekly diff --git a/.github/workflows/invalid_question.yml b/.github/workflows/invalid_question.yml index 5b0bd981..dfd2ddd9 100644 --- a/.github/workflows/invalid_question.yml +++ b/.github/workflows/invalid_question.yml @@ -10,7 +10,7 @@ jobs: ACTIONS_STEP_DEBUG: true steps: - name: Close Stale Issues - uses: actions/stale@v3.0.7 + uses: actions/stale@v4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue has been marked as invalid question, please give more information by following the `Question` template, if you believe there is a bug of GORM, please create a pull request that could reproduce the issue on [https://github.com/go-gorm/playground](https://github.com/go-gorm/playground), the issue will be closed in 2 days if no further activity occurs. most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ [Search Before Asking](https://stackoverflow.com/help/how-to-ask) ✨" diff --git a/.github/workflows/missing_playground.yml b/.github/workflows/missing_playground.yml index ea3207d6..cdb097de 100644 --- a/.github/workflows/missing_playground.yml +++ b/.github/workflows/missing_playground.yml @@ -10,7 +10,7 @@ jobs: ACTIONS_STEP_DEBUG: true steps: - name: Close Stale Issues - uses: actions/stale@v3.0.7 + uses: actions/stale@v4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout [https://github.com/go-gorm/playground](https://github.com/go-gorm/playground) for details. it will be closed in 2 days if no further activity occurs. if you are asking question, please use the `Question` template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ [Search Before Asking](https://stackoverflow.com/help/how-to-ask) ✨" diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 4511c378..d55a4699 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -8,4 +8,4 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v1 - name: golangci-lint - uses: reviewdog/action-golangci-lint@v1 + uses: reviewdog/action-golangci-lint@v2 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f9c1bece..d5419295 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: ACTIONS_STEP_DEBUG: true steps: - name: Close Stale Issues - uses: actions/stale@v3.0.7 + uses: actions/stale@v4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue has been automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days" diff --git a/tests/go.mod b/tests/go.mod index 815f8986..b623b363 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -3,14 +3,14 @@ module gorm.io/gorm/tests go 1.14 require ( - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/jinzhu/now v1.1.2 - github.com/lib/pq v1.6.0 - gorm.io/driver/mysql v1.0.5 + github.com/lib/pq v1.10.2 + gorm.io/driver/mysql v1.1.1 gorm.io/driver/postgres v1.1.0 gorm.io/driver/sqlite v1.1.4 gorm.io/driver/sqlserver v1.0.7 - gorm.io/gorm v1.21.9 + gorm.io/gorm v1.21.12 ) replace gorm.io/gorm => ../ From 82fe81530305257eb13f708d8fe5bd63c05cac01 Mon Sep 17 00:00:00 2001 From: SmallTianTian Date: Mon, 9 Aug 2021 13:20:22 +0800 Subject: [PATCH 3/6] fix: table couln't be reentrant (#4556) --- chainable_api.go | 7 +++---- tests/table_test.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/chainable_api.go b/chainable_api.go index d5a0907d..88279044 100644 --- a/chainable_api.go +++ b/chainable_api.go @@ -50,15 +50,14 @@ func (db *DB) Table(name string, args ...interface{}) (tx *DB) { tx.Statement.TableExpr = &clause.Expr{SQL: name, Vars: args} if results := tableRegexp.FindStringSubmatch(name); len(results) == 2 { tx.Statement.Table = results[1] - return } } else if tables := strings.Split(name, "."); len(tables) == 2 { tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)} tx.Statement.Table = tables[1] - return + } else { + tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)} + tx.Statement.Table = name } - - tx.Statement.Table = name return } diff --git a/tests/table_test.go b/tests/table_test.go index 0c6b3eb0..0289b7b8 100644 --- a/tests/table_test.go +++ b/tests/table_test.go @@ -30,6 +30,26 @@ func TestTable(t *testing.T) { t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) } + r = dryDB.Table("`people`").Table("`user`").Find(&User{}).Statement + if !regexp.MustCompile("SELECT \\* FROM `user`").MatchString(r.Statement.SQL.String()) { + t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) + } + + r = dryDB.Table("people as p").Table("user as u").Find(&User{}).Statement + if !regexp.MustCompile("SELECT \\* FROM user as u WHERE .u.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { + t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) + } + + r = dryDB.Table("people as p").Table("user").Find(&User{}).Statement + if !regexp.MustCompile("SELECT \\* FROM .user. WHERE .user.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { + t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) + } + + r = dryDB.Table("gorm.people").Table("user").Find(&User{}).Statement + if !regexp.MustCompile("SELECT \\* FROM .user. WHERE .user.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { + t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) + } + r = dryDB.Table("gorm.user").Select("name").Find(&User{}).Statement if !regexp.MustCompile("SELECT .name. FROM .gorm.\\..user. WHERE .user.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) From 21e85b89d68c3d9af5a7f23280471cff05dd2e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=87=AF=E5=BC=BA?= Date: Mon, 9 Aug 2021 13:23:44 +0800 Subject: [PATCH 4/6] Fix create with ignore migration (#4571) --- migrator/migrator.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 012ccf65..48db151e 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -167,10 +167,12 @@ func (m Migrator) CreateTable(values ...interface{}) error { for _, dbName := range stmt.Schema.DBNames { field := stmt.Schema.FieldsByDBName[dbName] - createTableSQL += "? ?" - hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(string(field.DataType)), "PRIMARY KEY") - values = append(values, clause.Column{Name: dbName}, m.DB.Migrator().FullDataTypeOf(field)) - createTableSQL += "," + if !field.IgnoreMigration { + createTableSQL += "? ?" + hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(string(field.DataType)), "PRIMARY KEY") + values = append(values, clause.Column{Name: dbName}, m.DB.Migrator().FullDataTypeOf(field)) + createTableSQL += "," + } } if !hasPrimaryKeyInDataType && len(stmt.Schema.PrimaryFields) > 0 { From a83d25e25e700f8a3c40dda048ac52b23bba31d5 Mon Sep 17 00:00:00 2001 From: Sungyun Hur Date: Wed, 11 Aug 2021 12:49:46 +0900 Subject: [PATCH 5/6] chore(logger): explicitly set config of Default Logger (#4605) --- logger/logger.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/logger/logger.go b/logger/logger.go index 98d1b32e..69d41113 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -64,9 +64,10 @@ type Interface interface { var ( Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), Config{}) Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), Config{ - SlowThreshold: 200 * time.Millisecond, - LogLevel: Warn, - Colorful: true, + SlowThreshold: 200 * time.Millisecond, + LogLevel: Warn, + IgnoreRecordNotFoundError: false, + Colorful: true, }) Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()} ) From 2b2f6e77af28e57e7bbea5962d58b1a7cb8ff47b Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Wed, 11 Aug 2021 16:20:21 +0800 Subject: [PATCH 6/6] Add SchemaName to NamingStrategy --- schema/naming.go | 20 ++++++++++++++++++++ schema/naming_test.go | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/schema/naming.go b/schema/naming.go index 47e313a7..8407bffa 100644 --- a/schema/naming.go +++ b/schema/naming.go @@ -4,6 +4,7 @@ import ( "crypto/sha1" "encoding/hex" "fmt" + "regexp" "strings" "unicode/utf8" @@ -13,6 +14,7 @@ import ( // Namer namer interface type Namer interface { TableName(table string) string + SchemaName(table string) string ColumnName(table, column string) string JoinTableName(joinTable string) string RelationshipFKName(Relationship) string @@ -41,6 +43,16 @@ func (ns NamingStrategy) TableName(str string) string { return ns.TablePrefix + inflection.Plural(ns.toDBName(str)) } +// SchemaName generate schema name from table name, don't guarantee it is the reverse value of TableName +func (ns NamingStrategy) SchemaName(table string) string { + table = strings.TrimPrefix(table, ns.TablePrefix) + + if ns.SingularTable { + return ns.toSchemaName(table) + } + return ns.toSchemaName(inflection.Singular(table)) +} + // ColumnName convert string to column name func (ns NamingStrategy) ColumnName(table, column string) string { return ns.toDBName(column) @@ -154,3 +166,11 @@ func (ns NamingStrategy) toDBName(name string) string { ret := buf.String() return ret } + +func (ns NamingStrategy) toSchemaName(name string) string { + result := strings.Replace(strings.Title(strings.Replace(name, "_", " ", -1)), " ", "", -1) + for _, initialism := range commonInitialisms { + result = regexp.MustCompile(strings.Title(strings.ToLower(initialism))+"([A-Z]|$|_)").ReplaceAllString(result, initialism+"$1") + } + return result +} diff --git a/schema/naming_test.go b/schema/naming_test.go index face9364..6add338e 100644 --- a/schema/naming_test.go +++ b/schema/naming_test.go @@ -33,6 +33,26 @@ func TestToDBName(t *testing.T) { t.Errorf("%v toName should equal %v, but got %v", key, value, ns.toDBName(key)) } } + + maps = map[string]string{ + "x": "X", + "user_restrictions": "UserRestriction", + "this_is_a_test": "ThisIsATest", + "abc_and_jkl": "AbcAndJkl", + "employee_id": "EmployeeID", + "field_x": "FieldX", + "http_and_smtp": "HTTPAndSMTP", + "http_server_handler_for_url_id": "HTTPServerHandlerForURLID", + "uuid": "UUID", + "http_url": "HTTPURL", + "sha256_hash": "Sha256Hash", + "this_is_actually_a_test_so_we_may_be_able_to_use_this_code_in_gorm_package_also_id_can_be_used_at_the_end_as_id": "ThisIsActuallyATestSoWeMayBeAbleToUseThisCodeInGormPackageAlsoIDCanBeUsedAtTheEndAsID", + } + for key, value := range maps { + if ns.SchemaName(key) != value { + t.Errorf("%v schema name should equal %v, but got %v", key, value, ns.SchemaName(key)) + } + } } func TestNamingStrategy(t *testing.T) {