Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update ignores Custom UpdatedAt time type #772

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.15.0 // indirect
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
gorm.io/hints v1.1.0 // indirect
Expand Down
24 changes: 20 additions & 4 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,26 @@ import (
func TestGORM(t *testing.T) {
user := User{Name: "jinzhu"}

DB.Create(&user)
if err := DB.Create(&user).Error; err != nil {
t.Fatal(err)
}

var st2 User
if err := DB.First(&st2, 1).Error; err != nil {
t.Fatal(err)
}

if st2.ID != 1 {
t.Fatalf("expected ID 1, got %d", st2.ID)
}

st2.Name = "new User"
if err := DB.Save(&st2).Error; err != nil {
t.Fatal(err)
}

var result User
if err := DB.First(&result, user.ID).Error; err != nil {
t.Errorf("Failed, got error: %v", err)
var st3 User
if err := DB.First(&st3, 1).Error; err != nil {
t.Fatal(err)
}
}
85 changes: 71 additions & 14 deletions models.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@ package main

import (
"database/sql"
"database/sql/driver"
"fmt"
"time"

"gorm.io/gorm"
"gorm.io/gorm/schema"
)

// User has one `Account` (has one), many `Pets` (has many) and `Toys` (has many - polymorphic)
// He works in a Company (belongs to), he has a Manager (belongs to - single-table), and also managed a Team (has many - single-table)
// He speaks many languages (many to many) and has many friends (many to many - single-table)
// His pet also has one Toy (has one - polymorphic)
type User struct {
gorm.Model
ID uint `gorm:"primarykey"`
Name string
Age uint
Birthday *time.Time
Account Account
Pets []*Pet
Toys []Toy `gorm:"polymorphic:Owner"`
CompanyID *int
Company Company
ManagerID *uint
Manager *User
Team []User `gorm:"foreignkey:ManagerID"`
Languages []Language `gorm:"many2many:UserSpeak"`
Friends []*User `gorm:"many2many:user_friends"`
Active bool
CreatedAt Time `gorm:"not null"`
UpdatedAt Time `gorm:"not null"`
}

type Account struct {
Expand Down Expand Up @@ -58,3 +50,68 @@ type Language struct {
Code string `gorm:"primarykey"`
Name string
}

type Time struct {
date time.Time
}

func NewTime(year, month, day, hour, min, sec int) Time {
return Time{
date: time.Date(year, time.Month(month), day, hour, min, sec, 0, time.UTC),
}
}

// GormDataType returns gorm common data type. This type is used for the field's column type.
func (Time) GormDataType() string {
return "time"
}

// GormDBDataType returns gorm DB data type based on the current using database.
func (Time) GormDBDataType(db *gorm.DB, field *schema.Field) string {
switch db.Dialector.Name() {
case "mysql":
return "TIME"
case "postgres":
return "TIME"
case "sqlserver":
return "TIME"
case "sqlite":
return "TEXT"
default:
return ""
}
}

// Scan implements sql.Scanner interface and scans value into Time,
func (t *Time) Scan(src interface{}) error {
switch v := src.(type) {
case []byte:
return t.setFromString(string(v))
case string:
return t.setFromString(v)
case time.Time:
t.setFromTime(v)
default:
return fmt.Errorf("failed to scan value: %v", v)
}

return nil
}

func (t *Time) setFromString(str string) error {
time, err := time.Parse(time.DateTime, str)
if err != nil {
return err
}
t.date = time
return nil
}

func (t *Time) setFromTime(src time.Time) {
*t = NewTime(src.Year(), int(src.Month()), src.Day(), src.Hour(), src.Minute(), src.Second())
}

// Value implements driver.Valuer interface and returns string format of Time.
func (t Time) Value() (driver.Value, error) {
return t.date.Format(time.DateTime), nil
}
Loading