Refactor gorm field
This commit is contained in:
		
							parent
							
								
									3c77eb0bb0
								
							
						
					
					
						commit
						69b851ed95
					
				@ -15,6 +15,13 @@ import (
 | 
				
			|||||||
	"gorm.io/gorm/utils"
 | 
						"gorm.io/gorm/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// special types' reflect type
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						TimeReflectType    = reflect.TypeOf(time.Time{})
 | 
				
			||||||
 | 
						TimePtrReflectType = reflect.TypeOf(&time.Time{})
 | 
				
			||||||
 | 
						ByteReflectType    = reflect.TypeOf(uint8(0))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type (
 | 
					type (
 | 
				
			||||||
	// DataType GORM data type
 | 
						// DataType GORM data type
 | 
				
			||||||
	DataType string
 | 
						DataType string
 | 
				
			||||||
@ -22,9 +29,6 @@ type (
 | 
				
			|||||||
	TimeType int64
 | 
						TimeType int64
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TimeReflectType time's reflect type
 | 
					 | 
				
			||||||
var TimeReflectType = reflect.TypeOf(time.Time{})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GORM time types
 | 
					// GORM time types
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	UnixTime        TimeType = 1
 | 
						UnixTime        TimeType = 1
 | 
				
			||||||
@ -103,6 +107,8 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
		Updatable:              true,
 | 
							Updatable:              true,
 | 
				
			||||||
		Readable:               true,
 | 
							Readable:               true,
 | 
				
			||||||
		PrimaryKey:             utils.CheckTruth(tagSetting["PRIMARYKEY"], tagSetting["PRIMARY_KEY"]),
 | 
							PrimaryKey:             utils.CheckTruth(tagSetting["PRIMARYKEY"], tagSetting["PRIMARY_KEY"]),
 | 
				
			||||||
 | 
							AutoIncrement:          utils.CheckTruth(tagSetting["AUTOINCREMENT"]),
 | 
				
			||||||
 | 
							HasDefaultValue:        utils.CheckTruth(tagSetting["AUTOINCREMENT"]),
 | 
				
			||||||
		NotNull:                utils.CheckTruth(tagSetting["NOT NULL"], tagSetting["NOTNULL"]),
 | 
							NotNull:                utils.CheckTruth(tagSetting["NOT NULL"], tagSetting["NOTNULL"]),
 | 
				
			||||||
		Unique:                 utils.CheckTruth(tagSetting["UNIQUE"]),
 | 
							Unique:                 utils.CheckTruth(tagSetting["UNIQUE"]),
 | 
				
			||||||
		Comment:                tagSetting["COMMENT"],
 | 
							Comment:                tagSetting["COMMENT"],
 | 
				
			||||||
@ -114,7 +120,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fieldValue := reflect.New(field.IndirectFieldType)
 | 
						fieldValue := reflect.New(field.IndirectFieldType)
 | 
				
			||||||
	// if field is valuer, used its value or first fields as data type
 | 
						// if field is valuer, used its value or first field as data type
 | 
				
			||||||
	valuer, isValuer := fieldValue.Interface().(driver.Valuer)
 | 
						valuer, isValuer := fieldValue.Interface().(driver.Valuer)
 | 
				
			||||||
	if isValuer {
 | 
						if isValuer {
 | 
				
			||||||
		if _, ok := fieldValue.Interface().(GormDataTypeInterface); !ok {
 | 
							if _, ok := fieldValue.Interface().(GormDataTypeInterface); !ok {
 | 
				
			||||||
@ -122,31 +128,37 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
				fieldValue = reflect.ValueOf(v)
 | 
									fieldValue = reflect.ValueOf(v)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Use the field struct's first field type as data type, e.g: use `string` for sql.NullString
 | 
				
			||||||
			var getRealFieldValue func(reflect.Value)
 | 
								var getRealFieldValue func(reflect.Value)
 | 
				
			||||||
			getRealFieldValue = func(v reflect.Value) {
 | 
								getRealFieldValue = func(v reflect.Value) {
 | 
				
			||||||
				rv := reflect.Indirect(v)
 | 
									var (
 | 
				
			||||||
				if rv.Kind() == reflect.Struct && !rv.Type().ConvertibleTo(TimeReflectType) {
 | 
										rv     = reflect.Indirect(v)
 | 
				
			||||||
					for i := 0; i < rv.Type().NumField(); i++ {
 | 
										rvType = rv.Type()
 | 
				
			||||||
						newFieldType := rv.Type().Field(i).Type
 | 
									)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if rv.Kind() == reflect.Struct && !rvType.ConvertibleTo(TimeReflectType) {
 | 
				
			||||||
 | 
										for i := 0; i < rvType.NumField(); i++ {
 | 
				
			||||||
 | 
											for key, value := range ParseTagSetting(rvType.Field(i).Tag.Get("gorm"), ";") {
 | 
				
			||||||
 | 
												if _, ok := field.TagSettings[key]; !ok {
 | 
				
			||||||
 | 
													field.TagSettings[key] = value
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for i := 0; i < rvType.NumField(); i++ {
 | 
				
			||||||
 | 
											newFieldType := rvType.Field(i).Type
 | 
				
			||||||
						for newFieldType.Kind() == reflect.Ptr {
 | 
											for newFieldType.Kind() == reflect.Ptr {
 | 
				
			||||||
							newFieldType = newFieldType.Elem()
 | 
												newFieldType = newFieldType.Elem()
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						fieldValue = reflect.New(newFieldType)
 | 
											fieldValue = reflect.New(newFieldType)
 | 
				
			||||||
 | 
											if rvType != reflect.Indirect(fieldValue).Type() {
 | 
				
			||||||
						if rv.Type() != reflect.Indirect(fieldValue).Type() {
 | 
					 | 
				
			||||||
							getRealFieldValue(fieldValue)
 | 
												getRealFieldValue(fieldValue)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if fieldValue.IsValid() {
 | 
											if fieldValue.IsValid() {
 | 
				
			||||||
							return
 | 
												return
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					 | 
				
			||||||
						for key, value := range ParseTagSetting(field.IndirectFieldType.Field(i).Tag.Get("gorm"), ";") {
 | 
					 | 
				
			||||||
							if _, ok := field.TagSettings[key]; !ok {
 | 
					 | 
				
			||||||
								field.TagSettings[key] = value
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -155,11 +167,6 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if val, ok := field.TagSettings["AUTOINCREMENT"]; ok && utils.CheckTruth(val) {
 | 
					 | 
				
			||||||
		field.AutoIncrement = true
 | 
					 | 
				
			||||||
		field.HasDefaultValue = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if num, ok := field.TagSettings["AUTOINCREMENTINCREMENT"]; ok {
 | 
						if num, ok := field.TagSettings["AUTOINCREMENTINCREMENT"]; ok {
 | 
				
			||||||
		field.AutoIncrementIncrement, _ = strconv.ParseInt(num, 10, 64)
 | 
							field.AutoIncrementIncrement, _ = strconv.ParseInt(num, 10, 64)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -218,7 +225,6 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		field.DataType = String
 | 
							field.DataType = String
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
							if field.HasDefaultValue && !skipParseDefaultValue {
 | 
				
			||||||
			field.DefaultValue = strings.Trim(field.DefaultValue, "'")
 | 
								field.DefaultValue = strings.Trim(field.DefaultValue, "'")
 | 
				
			||||||
			field.DefaultValue = strings.Trim(field.DefaultValue, `"`)
 | 
								field.DefaultValue = strings.Trim(field.DefaultValue, `"`)
 | 
				
			||||||
@ -229,17 +235,15 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
			field.DataType = Time
 | 
								field.DataType = Time
 | 
				
			||||||
		} else if fieldValue.Type().ConvertibleTo(TimeReflectType) {
 | 
							} else if fieldValue.Type().ConvertibleTo(TimeReflectType) {
 | 
				
			||||||
			field.DataType = Time
 | 
								field.DataType = Time
 | 
				
			||||||
		} else if fieldValue.Type().ConvertibleTo(reflect.TypeOf(&time.Time{})) {
 | 
							} else if fieldValue.Type().ConvertibleTo(TimePtrReflectType) {
 | 
				
			||||||
			field.DataType = Time
 | 
								field.DataType = Time
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case reflect.Array, reflect.Slice:
 | 
						case reflect.Array, reflect.Slice:
 | 
				
			||||||
		if reflect.Indirect(fieldValue).Type().Elem() == reflect.TypeOf(uint8(0)) {
 | 
							if reflect.Indirect(fieldValue).Type().Elem() == ByteReflectType {
 | 
				
			||||||
			field.DataType = Bytes
 | 
								field.DataType = Bytes
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	field.GORMDataType = field.DataType
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if dataTyper, ok := fieldValue.Interface().(GormDataTypeInterface); ok {
 | 
						if dataTyper, ok := fieldValue.Interface().(GormDataTypeInterface); ok {
 | 
				
			||||||
		field.DataType = DataType(dataTyper.GormDataType())
 | 
							field.DataType = DataType(dataTyper.GormDataType())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -339,8 +343,9 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, ok := field.TagSettings["EMBEDDED"]; field.GORMDataType != Time && field.GORMDataType != Bytes &&
 | 
						// Normal anonymous field or having `EMBEDDED` tag
 | 
				
			||||||
		(ok || (fieldStruct.Anonymous && !isValuer && (field.Creatable || field.Updatable || field.Readable))) {
 | 
						if _, ok := field.TagSettings["EMBEDDED"]; ok || (field.GORMDataType != Time && field.GORMDataType != Bytes && !isValuer &&
 | 
				
			||||||
 | 
							fieldStruct.Anonymous && (field.Creatable || field.Updatable || field.Readable)) {
 | 
				
			||||||
		kind := reflect.Indirect(fieldValue).Kind()
 | 
							kind := reflect.Indirect(fieldValue).Kind()
 | 
				
			||||||
		switch kind {
 | 
							switch kind {
 | 
				
			||||||
		case reflect.Struct:
 | 
							case reflect.Struct:
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ require (
 | 
				
			|||||||
	github.com/jinzhu/now v1.1.4
 | 
						github.com/jinzhu/now v1.1.4
 | 
				
			||||||
	github.com/lib/pq v1.10.4
 | 
						github.com/lib/pq v1.10.4
 | 
				
			||||||
	github.com/mattn/go-sqlite3 v1.14.11 // indirect
 | 
						github.com/mattn/go-sqlite3 v1.14.11 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.0.0-20220208233918-bba287dce954 // indirect
 | 
						golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506 // indirect
 | 
				
			||||||
	gorm.io/driver/mysql v1.2.3
 | 
						gorm.io/driver/mysql v1.2.3
 | 
				
			||||||
	gorm.io/driver/postgres v1.2.3
 | 
						gorm.io/driver/postgres v1.2.3
 | 
				
			||||||
	gorm.io/driver/sqlite v1.2.6
 | 
						gorm.io/driver/sqlite v1.2.6
 | 
				
			||||||
@ -18,3 +18,5 @@ require (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
replace gorm.io/gorm => ../
 | 
					replace gorm.io/gorm => ../
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					replace gorm.io/driver/sqlserver => /Users/jinzhu/Projects/gorm/sqlserver
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user