Repository: go-gorm/gorm
Pull request #4992 (2022-01-12 04:12:37)

time.Time, []byte type add alias support. (rebase master)

<!--
Make sure these boxes checked before submitting your pull request.

For significant changes, please open an issue to make an agreement on an implementation design/plan first before starting it.
-->

- [x] Do only one thing
- [x] Non breaking API changes
- [x] Tested

### What did this pull request do?

<!--
provide a general description of the code changes in your pull request
-->

1, time.Time, []byte type add alias support.
2, []byte alias type, fixed statement bind var parameter.

### User Case Description

<!-- Your use case -->
```go
func main() {        
        type ID int64
	type TIME time.Time
	type BYTES []byte
	type TypeAlias struct {
		ID
		TIME  `gorm:"column:ftime;type:timestamptz"`
		BYTES `gorm:"column:fbytes;type:bytea"`
	}

	db, err := gorm.Open(postgres.New(postgres.Config{
		DSN: `dsn`,
		PreferSimpleProtocol: false,
	}), &gorm.Config{
		Logger:                 logger.Default.LogMode(logger.Info),
		SkipDefaultTransaction: true,
	})
	if err != nil {
		log.Fatal(err)
	}

	al := &TypeAlias{
		ID:    2,
		TIME:  TIME(time.Now()),
		BYTES: []byte{1, 2, 3},
	}

	if err := db.AutoMigrate(al); err != nil {
		t.Fatal(err)
	}

	if err := db.Create(al).Error; err != nil {
		t.Fatal(err)
	}

	al1 := &TypeAlias{}
	if err := db.First(al1).Error; err != nil {
		t.Fatal(err)
	}
}
```


Patch:
diff --git a/schema/field.go b/schema/field.go
index d4f879c..485bbdf 100644
--- a/schema/field.go
+++ b/schema/field.go
@@ -346,7 +346,8 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 		}
 	}
 
-	if _, ok := field.TagSettings["EMBEDDED"]; ok || (fieldStruct.Anonymous && !isValuer && (field.Creatable || field.Updatable || field.Readable)) {
+	if _, ok := field.TagSettings["EMBEDDED"]; field.GORMDataType != Time && field.GORMDataType != Bytes &&
+		(ok || (fieldStruct.Anonymous && !isValuer && (field.Creatable || field.Updatable || field.Readable))) {
 		kind := reflect.Indirect(fieldValue).Kind()
 		switch kind {
 		case reflect.Struct:
diff --git a/statement.go b/statement.go
index f69339d..146722a 100644
--- a/statement.go
+++ b/statement.go
@@ -232,6 +232,9 @@ func (stmt *Statement) AddVar(writer clause.Writer, vars ...interface{}) {
 			case reflect.Slice, reflect.Array:
 				if rv.Len() == 0 {
 					writer.WriteString("(NULL)")
+				} else if rv.Type().Elem() == reflect.TypeOf(uint8(0)) {
+					stmt.Vars = append(stmt.Vars, v)
+					stmt.DB.Dialector.BindVarTo(writer, stmt, v)
 				} else {
 					writer.WriteByte('(')
 					for i := 0; i < rv.Len(); i++ {


Test patch:
diff --git a/schema/field_test.go b/schema/field_test.go
index 2cf2d08..8fa46b8 100644
--- a/schema/field_test.go
+++ b/schema/field_test.go
@@ -262,21 +262,24 @@ func TestParseFieldWithPermission(t *testing.T) {
 }
 
 type (
-	ID        int64
-	INT       int
-	INT8      int8
-	INT16     int16
-	INT32     int32
-	INT64     int64
-	UINT      uint
-	UINT8     uint8
-	UINT16    uint16
-	UINT32    uint32
-	UINT64    uint64
-	FLOAT32   float32
-	FLOAT64   float64
-	BOOL      bool
-	STRING    string
+	ID      int64
+	INT     int
+	INT8    int8
+	INT16   int16
+	INT32   int32
+	INT64   int64
+	UINT    uint
+	UINT8   uint8
+	UINT16  uint16
+	UINT32  uint32
+	UINT64  uint64
+	FLOAT32 float32
+	FLOAT64 float64
+	BOOL    bool
+	STRING  string
+	TIME    time.Time
+	BYTES   []byte
+
 	TypeAlias struct {
 		ID
 		INT     `gorm:"column:fint"`
@@ -293,6 +296,8 @@ type (
 		FLOAT64 `gorm:"column:ffloat64"`
 		BOOL    `gorm:"column:fbool"`
 		STRING  `gorm:"column:fstring"`
+		TIME    `gorm:"column:ftime"`
+		BYTES   `gorm:"column:fbytes"`
 	}
 )
 
@@ -318,6 +323,8 @@ func TestTypeAliasField(t *testing.T) {
 		{Name: "FLOAT64", DBName: "ffloat64", BindNames: []string{"FLOAT64"}, DataType: schema.Float, Creatable: true, Updatable: true, Readable: true, Size: 64, Tag: `gorm:"column:ffloat64"`},
 		{Name: "BOOL", DBName: "fbool", BindNames: []string{"BOOL"}, DataType: schema.Bool, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:fbool"`},
 		{Name: "STRING", DBName: "fstring", BindNames: []string{"STRING"}, DataType: schema.String, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:fstring"`},
+		{Name: "TIME", DBName: "ftime", BindNames: []string{"TIME"}, DataType: schema.Time, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:ftime"`},
+		{Name: "BYTES", DBName: "fbytes", BindNames: []string{"BYTES"}, DataType: schema.Bytes, Creatable: true, Updatable: true, Readable: true, Tag: `gorm:"column:fbytes"`},
 	}
 
 	for _, f := range fields {