Merge branch 'go-gorm:master' into master

This commit is contained in:
Fu Zeng Yao 2021-08-13 16:03:34 +08:00 committed by GitHub
commit 8bb3b959c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 115 additions and 26 deletions

15
.github/dependabot.yml vendored Normal file
View File

@ -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

View File

@ -10,7 +10,7 @@ jobs:
ACTIONS_STEP_DEBUG: true ACTIONS_STEP_DEBUG: true
steps: steps:
- name: Close Stale Issues - name: Close Stale Issues
uses: actions/stale@v3.0.7 uses: actions/stale@v4
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} 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) ✨" 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) ✨"

View File

@ -10,7 +10,7 @@ jobs:
ACTIONS_STEP_DEBUG: true ACTIONS_STEP_DEBUG: true
steps: steps:
- name: Close Stale Issues - name: Close Stale Issues
uses: actions/stale@v3.0.7 uses: actions/stale@v4
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} 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) ✨" 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) ✨"

View File

@ -8,4 +8,4 @@ jobs:
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: golangci-lint - name: golangci-lint
uses: reviewdog/action-golangci-lint@v1 uses: reviewdog/action-golangci-lint@v2

View File

@ -10,7 +10,7 @@ jobs:
ACTIONS_STEP_DEBUG: true ACTIONS_STEP_DEBUG: true
steps: steps:
- name: Close Stale Issues - name: Close Stale Issues
uses: actions/stale@v3.0.7 uses: actions/stale@v4
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} 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" 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"

View File

@ -50,15 +50,14 @@ func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
tx.Statement.TableExpr = &clause.Expr{SQL: name, Vars: args} tx.Statement.TableExpr = &clause.Expr{SQL: name, Vars: args}
if results := tableRegexp.FindStringSubmatch(name); len(results) == 2 { if results := tableRegexp.FindStringSubmatch(name); len(results) == 2 {
tx.Statement.Table = results[1] tx.Statement.Table = results[1]
return
} }
} else if tables := strings.Split(name, "."); len(tables) == 2 { } else if tables := strings.Split(name, "."); len(tables) == 2 {
tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)} tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)}
tx.Statement.Table = tables[1] 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 return
} }
@ -209,12 +208,14 @@ func (db *DB) Order(value interface{}) (tx *DB) {
tx.Statement.AddClause(clause.OrderBy{ tx.Statement.AddClause(clause.OrderBy{
Columns: []clause.OrderByColumn{v}, Columns: []clause.OrderByColumn{v},
}) })
default: case string:
tx.Statement.AddClause(clause.OrderBy{ if v != "" {
Columns: []clause.OrderByColumn{{ tx.Statement.AddClause(clause.OrderBy{
Column: clause.Column{Name: fmt.Sprint(value), Raw: true}, Columns: []clause.OrderByColumn{{
}}, Column: clause.Column{Name: v, Raw: true},
}) }},
})
}
} }
return return
} }

View File

@ -64,9 +64,10 @@ type Interface interface {
var ( var (
Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), Config{}) Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), Config{})
Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), Config{ Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), Config{
SlowThreshold: 200 * time.Millisecond, SlowThreshold: 200 * time.Millisecond,
LogLevel: Warn, LogLevel: Warn,
Colorful: true, IgnoreRecordNotFoundError: false,
Colorful: true,
}) })
Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()} Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()}
) )

View File

@ -167,10 +167,12 @@ func (m Migrator) CreateTable(values ...interface{}) error {
for _, dbName := range stmt.Schema.DBNames { for _, dbName := range stmt.Schema.DBNames {
field := stmt.Schema.FieldsByDBName[dbName] field := stmt.Schema.FieldsByDBName[dbName]
createTableSQL += "? ?" if !field.IgnoreMigration {
hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(string(field.DataType)), "PRIMARY KEY") createTableSQL += "? ?"
values = append(values, clause.Column{Name: dbName}, m.DB.Migrator().FullDataTypeOf(field)) hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(string(field.DataType)), "PRIMARY KEY")
createTableSQL += "," values = append(values, clause.Column{Name: dbName}, m.DB.Migrator().FullDataTypeOf(field))
createTableSQL += ","
}
} }
if !hasPrimaryKeyInDataType && len(stmt.Schema.PrimaryFields) > 0 { if !hasPrimaryKeyInDataType && len(stmt.Schema.PrimaryFields) > 0 {

View File

@ -4,6 +4,7 @@ import (
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"regexp"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -13,6 +14,7 @@ import (
// Namer namer interface // Namer namer interface
type Namer interface { type Namer interface {
TableName(table string) string TableName(table string) string
SchemaName(table string) string
ColumnName(table, column string) string ColumnName(table, column string) string
JoinTableName(joinTable string) string JoinTableName(joinTable string) string
RelationshipFKName(Relationship) string RelationshipFKName(Relationship) string
@ -41,6 +43,16 @@ func (ns NamingStrategy) TableName(str string) string {
return ns.TablePrefix + inflection.Plural(ns.toDBName(str)) 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 // ColumnName convert string to column name
func (ns NamingStrategy) ColumnName(table, column string) string { func (ns NamingStrategy) ColumnName(table, column string) string {
return ns.toDBName(column) return ns.toDBName(column)
@ -154,3 +166,11 @@ func (ns NamingStrategy) toDBName(name string) string {
ret := buf.String() ret := buf.String()
return ret 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
}

View File

@ -33,6 +33,26 @@ func TestToDBName(t *testing.T) {
t.Errorf("%v toName should equal %v, but got %v", key, value, ns.toDBName(key)) 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) { func TestNamingStrategy(t *testing.T) {

View File

@ -3,14 +3,14 @@ module gorm.io/gorm/tests
go 1.14 go 1.14
require ( require (
github.com/google/uuid v1.2.0 github.com/google/uuid v1.3.0
github.com/jinzhu/now v1.1.2 github.com/jinzhu/now v1.1.2
github.com/lib/pq v1.6.0 github.com/lib/pq v1.10.2
gorm.io/driver/mysql v1.0.5 gorm.io/driver/mysql v1.1.1
gorm.io/driver/postgres v1.1.0 gorm.io/driver/postgres v1.1.0
gorm.io/driver/sqlite v1.1.4 gorm.io/driver/sqlite v1.1.4
gorm.io/driver/sqlserver v1.0.7 gorm.io/driver/sqlserver v1.0.7
gorm.io/gorm v1.21.9 gorm.io/gorm v1.21.12
) )
replace gorm.io/gorm => ../ replace gorm.io/gorm => ../

View File

@ -842,7 +842,17 @@ func TestSearchWithEmptyChain(t *testing.T) {
func TestOrder(t *testing.T) { func TestOrder(t *testing.T) {
dryDB := DB.Session(&gorm.Session{DryRun: true}) 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()) { 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()) t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String())
} }

View File

@ -30,6 +30,26 @@ func TestTable(t *testing.T) {
t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) 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 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()) { 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()) t.Errorf("Table with escape character, got %v", r.Statement.SQL.String())