Skip to content

Commit

Permalink
Refactor DefaultValue
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Nov 17, 2014
1 parent 064d913 commit 75819b2
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 32 deletions.
32 changes: 5 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -974,8 +974,8 @@ If you have an existing database schema, and the primary key field is different
```go
type Animal struct {
AnimalId int64 `gorm:"primary_key:yes"`
Birthday time.Time `sql:"DEFAULT:NOW()"`
Name string `sql:"default:'galeone'"`
Birthday time.Time `sql:"DEFAULT:current_timestamp"`
Name string `sql:"default:'galeone'"`
Age int64
}
```
Expand All @@ -992,44 +992,22 @@ type Animal struct {

## Default values

If you have defined a default value in the `sql` tag (see the struct Animal above) the generated queries will not contains the value for these fields if is not set.
If you have defined a default value in the `sql` tag (see the struct Animal above) the generated create/update SQl will ignore these fields if is set blank data.

Eg.

```go
db.Save(&Animal{Age: 99})
db.Create(&Animal{Age: 99, Name: ""})
```

The generated query will be:

```sql
INSERT INTO animals("birthday","age","name") values(NOW(), '99', 'galeone')
INSERT INTO animals("age") values('99');
```

The same thing occurs in update statements.

You should fetch the value again to get the default updated values in the struct.

We can't do the same thing of the primary key (that is always filled with the right value) because default SQL values can be expressions and thus be different from the fields' type (eg. a time.Time fiels has a default value of "NOW()")

So the right way to do an update/insert statement and be sure to get the default values in the struct is

```go
//Insert
var animal Animal
animal.Age = 99
db.Save(&animal)
db.First(&animal, animal.AnimalId)
// Now wo have the animal struct with:
// Birthday: the insert time
// Name: the string galeone
// Age: the setted one -> 99

// For the update statements is the same
// First save the struct
// Than fetch it back again
```

## More examples with query chain

```go
Expand Down
3 changes: 1 addition & 2 deletions callback_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gorm

import (
"fmt"
"reflect"
"strings"
)

Expand All @@ -27,7 +26,7 @@ func Create(scope *Scope) {
var sqls, columns []string
for _, field := range scope.Fields() {
if field.IsNormal && (!field.IsPrimaryKey || !scope.PrimaryKeyZero()) {
if field.DefaultValue != nil && reflect.DeepEqual(field.Field.Interface(), reflect.Zero(field.Field.Type()).Interface()) {
if field.DefaultValue != nil && field.IsBlank {
continue
}
columns = append(columns, scope.Quote(field.DBName))
Expand Down
3 changes: 1 addition & 2 deletions callback_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gorm

import (
"fmt"
"reflect"
"strings"
)

Expand Down Expand Up @@ -50,7 +49,7 @@ func Update(scope *Scope) {
} else {
for _, field := range scope.Fields() {
if !field.IsPrimaryKey && field.IsNormal && !field.IsIgnored {
if field.DefaultValue != nil && reflect.DeepEqual(field.Field.Interface(), reflect.Zero(field.Field.Type()).Interface()) {
if field.DefaultValue != nil && field.IsBlank {
continue
}
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface())))
Expand Down
2 changes: 1 addition & 1 deletion structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ type Animal struct {
Counter uint64 `gorm:"primary_key:yes"`
Name string `sql:"DEFAULT:'galeone'"`
From string //test reserved sql keyword as field name
Age time.Time `sql:"DEFAULT:NOW()"`
Age time.Time `sql:"DEFAULT:current_timestamp"`
CreatedAt time.Time
UpdatedAt time.Time
}
Expand Down

0 comments on commit 75819b2

Please sign in to comment.