From ec850f8b6013469ce28bbbf03cc5be0dc3ca4761 Mon Sep 17 00:00:00 2001 From: Icemap Date: Fri, 13 Jan 2023 16:27:35 +0800 Subject: [PATCH] feat: support auto_random --- migrator.go | 1 + migrator/column_type.go | 6 ++++++ model.go | 7 ++++--- schema/field.go | 10 +++++++--- schema/relationship.go | 23 ++++++++++++----------- schema/schema.go | 13 ++++++++----- tests/connpool_test.go | 8 +++++--- tests/go.mod | 1 + tests/tests_all.sh | 3 ++- 9 files changed, 46 insertions(+), 26 deletions(-) diff --git a/migrator.go b/migrator.go index 882fc4cc..6712c264 100644 --- a/migrator.go +++ b/migrator.go @@ -42,6 +42,7 @@ type ColumnType interface { ColumnType() (columnType string, ok bool) // varchar(64) PrimaryKey() (isPrimaryKey bool, ok bool) AutoIncrement() (isAutoIncrement bool, ok bool) + AutoRandom() (isAutoRandom bool, ok bool) Length() (length int64, ok bool) DecimalSize() (precision int64, scale int64, ok bool) Nullable() (nullable bool, ok bool) diff --git a/migrator/column_type.go b/migrator/column_type.go index c6fdd6b2..6d025a3a 100644 --- a/migrator/column_type.go +++ b/migrator/column_type.go @@ -14,6 +14,7 @@ type ColumnType struct { PrimaryKeyValue sql.NullBool UniqueValue sql.NullBool AutoIncrementValue sql.NullBool + AutoRandomValue sql.NullBool LengthValue sql.NullInt64 DecimalSizeValue sql.NullInt64 ScaleValue sql.NullInt64 @@ -59,6 +60,11 @@ func (ct ColumnType) AutoIncrement() (isAutoIncrement bool, ok bool) { return ct.AutoIncrementValue.Bool, ct.AutoIncrementValue.Valid } +// AutoRandom returns the column is auto random or not. +func (ct ColumnType) AutoRandom() (isAutoRandom bool, ok bool) { + return ct.AutoRandomValue.Bool, ct.AutoRandomValue.Valid +} + // Length returns the column type length for variable length column types func (ct ColumnType) Length() (length int64, ok bool) { if ct.LengthValue.Valid { diff --git a/model.go b/model.go index 3334d17c..fa705df1 100644 --- a/model.go +++ b/model.go @@ -4,9 +4,10 @@ import "time" // Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt // It may be embedded into your model or you may build your own model without it -// type User struct { -// gorm.Model -// } +// +// type User struct { +// gorm.Model +// } type Model struct { ID uint `gorm:"primarykey"` CreatedAt time.Time diff --git a/schema/field.go b/schema/field.go index 1589d984..a2c0d6ee 100644 --- a/schema/field.go +++ b/schema/field.go @@ -59,6 +59,7 @@ type Field struct { PrimaryKey bool AutoIncrement bool AutoIncrementIncrement int64 + AutoRandom bool Creatable bool Updatable bool Readable bool @@ -111,7 +112,8 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { Readable: true, PrimaryKey: utils.CheckTruth(tagSetting["PRIMARYKEY"], tagSetting["PRIMARY_KEY"]), AutoIncrement: utils.CheckTruth(tagSetting["AUTOINCREMENT"]), - HasDefaultValue: utils.CheckTruth(tagSetting["AUTOINCREMENT"]), + AutoRandom: utils.CheckTruth(tagSetting["AUTORANDOM"]), + HasDefaultValue: utils.CheckTruth(tagSetting["AUTOINCREMENT"], tagSetting["AUTORANDOM"]), NotNull: utils.CheckTruth(tagSetting["NOT NULL"], tagSetting["NOTNULL"]), Unique: utils.CheckTruth(tagSetting["UNIQUE"]), Comment: tagSetting["COMMENT"], @@ -406,11 +408,13 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { if !utils.CheckTruth(ef.TagSettings["PRIMARYKEY"], ef.TagSettings["PRIMARY_KEY"]) { ef.PrimaryKey = false - if val, ok := ef.TagSettings["AUTOINCREMENT"]; !ok || !utils.CheckTruth(val) { + if autoIncrVal, ok := ef.TagSettings["AUTOINCREMENT"]; !ok || !utils.CheckTruth(autoIncrVal) { ef.AutoIncrement = false + } else if autoRandVal, ok := ef.TagSettings["AUTORANDOM"]; !ok || !utils.CheckTruth(autoRandVal) { + ef.AutoRandom = false } - if !ef.AutoIncrement && ef.DefaultValue == "" { + if !ef.AutoIncrement && !ef.AutoRandom && ef.DefaultValue == "" { ef.HasDefaultValue = false } } diff --git a/schema/relationship.go b/schema/relationship.go index 9436f283..6b019e9e 100644 --- a/schema/relationship.go +++ b/schema/relationship.go @@ -123,16 +123,17 @@ func (schema *Schema) parseRelation(field *Field) *Relationship { } // User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner` -// type User struct { -// Toys []Toy `gorm:"polymorphic:Owner;"` -// } -// type Pet struct { -// Toy Toy `gorm:"polymorphic:Owner;"` -// } -// type Toy struct { -// OwnerID int -// OwnerType string -// } +// +// type User struct { +// Toys []Toy `gorm:"polymorphic:Owner;"` +// } +// type Pet struct { +// Toy Toy `gorm:"polymorphic:Owner;"` +// } +// type Toy struct { +// OwnerID int +// OwnerType string +// } func (schema *Schema) buildPolymorphicRelation(relation *Relationship, field *Field, polymorphic string) { relation.Polymorphic = &Polymorphic{ Value: schema.Table, @@ -641,7 +642,7 @@ func (rel *Relationship) ToQueryConditions(ctx context.Context, reflectValue ref } func copyableDataType(str DataType) bool { - for _, s := range []string{"auto_increment", "primary key"} { + for _, s := range []string{"increment", "primary key"} { if strings.Contains(strings.ToLower(string(str)), s) { return false } diff --git a/schema/schema.go b/schema/schema.go index 21e71c21..69ff323c 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -239,12 +239,15 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam switch field.GORMDataType { case Int, Uint: if _, ok := field.TagSettings["AUTOINCREMENT"]; !ok { - if !field.HasDefaultValue || field.DefaultValueInterface != nil { - schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field) - } + // also not have AUTORANDOM tag + if _, ok := field.TagSettings["AUTORANDOM"]; !ok { + if !field.HasDefaultValue || field.DefaultValueInterface != nil { + schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field) + } - field.HasDefaultValue = true - field.AutoIncrement = true + field.HasDefaultValue = true + field.AutoIncrement = true + } } case String: if _, ok := field.TagSettings["PRIMARYKEY"]; !ok { diff --git a/tests/connpool_test.go b/tests/connpool_test.go index 42e029bc..e0e1c771 100644 --- a/tests/connpool_test.go +++ b/tests/connpool_test.go @@ -48,9 +48,11 @@ func (c *wrapperConnPool) Ping() error { } // If you use BeginTx returned *sql.Tx as shown below then you can't record queries in a transaction. -// func (c *wrapperConnPool) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { -// return c.db.BeginTx(ctx, opts) -// } +// +// func (c *wrapperConnPool) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { +// return c.db.BeginTx(ctx, opts) +// } +// // You should use BeginTx returned gorm.Tx which could wrap *sql.Tx then you can record all queries. func (c *wrapperConnPool) BeginTx(ctx context.Context, opts *sql.TxOptions) (gorm.ConnPool, error) { tx, err := c.db.BeginTx(ctx, opts) diff --git a/tests/go.mod b/tests/go.mod index 2ba97179..acc0cf0e 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -8,6 +8,7 @@ require ( github.com/lib/pq v1.10.7 github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/microsoft/go-mssqldb v0.19.0 // indirect + golang.org/x/crypto v0.5.0 // indirect gorm.io/driver/mysql v1.4.5 gorm.io/driver/postgres v1.4.6 gorm.io/driver/sqlite v1.4.4 diff --git a/tests/tests_all.sh b/tests/tests_all.sh index 5b9bae97..155f8e6c 100755 --- a/tests/tests_all.sh +++ b/tests/tests_all.sh @@ -1,6 +1,7 @@ #!/bin/bash -e -dialects=("sqlite" "mysql" "postgres" "sqlserver") +# dialects=("sqlite" "mysql" "postgres" "sqlserver") +dialects=("tidb") if [[ $(pwd) == *"gorm/tests"* ]]; then cd ..