Skip to content

Commit

Permalink
Support extra options for inserting, querying, deleting, updating SQL,
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Feb 15, 2016
1 parent f9c6d17 commit c9dfd80
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 12 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ db.Create(&user)
//// INSERT INTO "languages" ("name") VALUES ('EN');
//// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 2);
//// COMMIT;


// Add extra SQL option for inserting SQL
db.Set("gorm:insert_option", "ON CONFLICT").Create(&product)
// INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT;
```

Refer [Associations](#associations) for more details
Expand All @@ -281,6 +286,10 @@ db.Find(&users)
// Get record with primary key
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;

// Add extra SQL option for selecting SQL
db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)
//// SELECT * FROM users WHERE id = 10 FOR UPDATE;
```

### Query With Where (Plain SQL)
Expand Down Expand Up @@ -460,6 +469,10 @@ db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "acti
// Update multiple attributes if they are changed (update with struct only works with none zero values)
db.Model(&user).Updates(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

// Add extra SQL option for updating SQL
db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name, "hello")
//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
```
### Update Without Callbacks
Expand Down Expand Up @@ -513,6 +526,10 @@ DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("qua
// Delete an existing record
db.Delete(&email)
//// DELETE from emails where id=10;
// Add extra SQL option for deleting SQL
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
```
### Batch Delete
Expand Down
17 changes: 14 additions & 3 deletions callback_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,34 @@ func createCallback(scope *Scope) {
returningColumn = "*"
quotedTableName = scope.QuotedTableName()
primaryField = scope.PrimaryField()
extraOption string
)

if str, ok := scope.Get("gorm:insert_option"); ok {
extraOption = fmt.Sprint(str)
}

if primaryField != nil {
returningColumn = scope.Quote(primaryField.DBName)
}

lastInsertIdReturningSuffix := scope.Dialect().LastInsertIdReturningSuffix(quotedTableName, returningColumn)

if len(columns) == 0 {
scope.Raw(fmt.Sprintf("INSERT INTO %v DEFAULT VALUES %v", quotedTableName, lastInsertIdReturningSuffix))
scope.Raw(fmt.Sprintf(
"INSERT INTO %v DEFAULT VALUES%v%v",
quotedTableName,
addExtraSpaceIfExist(extraOption),
addExtraSpaceIfExist(lastInsertIdReturningSuffix),
))
} else {
scope.Raw(fmt.Sprintf(
"INSERT INTO %v (%v) VALUES (%v) %v",
"INSERT INTO %v (%v) VALUES (%v)%v%v",
scope.QuotedTableName(),
strings.Join(columns, ","),
strings.Join(placeholders, ","),
lastInsertIdReturningSuffix,
addExtraSpaceIfExist(extraOption),
addExtraSpaceIfExist(lastInsertIdReturningSuffix),
))
}

Expand Down
25 changes: 18 additions & 7 deletions callback_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,26 @@ func beforeDeleteCallback(scope *Scope) {
// deleteCallback used to delete data from database or set deleted_at to current time (when using with soft delete)
func deleteCallback(scope *Scope) {
if !scope.HasError() {
var extraOption string
if str, ok := scope.Get("gorm:delete_option"); ok {
extraOption = fmt.Sprint(str)
}

if !scope.Search.Unscoped && scope.HasColumn("DeletedAt") {
scope.Raw(
fmt.Sprintf("UPDATE %v SET deleted_at=%v %v",
scope.QuotedTableName(),
scope.AddToVars(NowFunc()),
scope.CombinedConditionSql(),
)).Exec()
scope.Raw(fmt.Sprintf(
"UPDATE %v SET deleted_at=%v%v%v",
scope.QuotedTableName(),
scope.AddToVars(NowFunc()),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
)).Exec()
} else {
scope.Raw(fmt.Sprintf("DELETE FROM %v %v", scope.QuotedTableName(), scope.CombinedConditionSql())).Exec()
scope.Raw(fmt.Sprintf(
"DELETE FROM %v%v%v",
scope.QuotedTableName(),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
)).Exec()
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion callback_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ func queryCallback(scope *Scope) {
scope.prepareQuerySql()

if !scope.HasError() {
var extraOption string
if str, ok := scope.Get("gorm:query_option"); ok {
extraOption = fmt.Sprint(str)
}
scope.db.RowsAffected = 0
if rows, err := scope.SqlDB().Query(scope.Sql, scope.SqlVars...); scope.Err(err) == nil {

if rows, err := scope.SqlDB().Query(scope.Sql+addExtraSpaceIfExist(extraOption), scope.SqlVars...); scope.Err(err) == nil {
defer rows.Close()

columns, _ := rows.Columns()
Expand Down
11 changes: 10 additions & 1 deletion callback_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,18 @@ func updateCallback(scope *Scope) {
}
}

var extraOption string
if str, ok := scope.Get("gorm:update_option"); ok {
extraOption = fmt.Sprint(str)
}

if len(sqls) > 0 {
scope.Raw(fmt.Sprintf(
"UPDATE %v SET %v %v", scope.QuotedTableName(), strings.Join(sqls, ", "), scope.CombinedConditionSql(),
"UPDATE %v SET %v%v%v",
scope.QuotedTableName(),
strings.Join(sqls, ", "),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
)).Exec()
}
}
Expand Down
7 changes: 7 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,10 @@ func getValueFromFields(value reflect.Value, fieldNames []string) (results []int
}
return
}

func addExtraSpaceIfExist(str string) string {
if str != "" {
return " " + str
}
return ""
}

0 comments on commit c9dfd80

Please sign in to comment.