diff --git a/.gitignore b/.gitignore index 117f92f5..1ce790a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ documents coverage.txt _book + +.idea \ No newline at end of file diff --git a/callback_create.go b/callback_create.go index 3527858b..0e239534 100644 --- a/callback_create.go +++ b/callback_create.go @@ -1,6 +1,7 @@ package gorm import ( + "database/sql" "fmt" "strings" ) @@ -65,7 +66,8 @@ func createCallback(scope *Scope) { scope.InstanceSet("gorm:blank_columns_with_default_value", blankColumnsWithDefaultValue) } else if !field.IsPrimaryKey || !field.IsBlank { columns = append(columns, scope.Quote(field.DBName)) - placeholders = append(placeholders, scope.AddToVars(field.Field.Interface())) + arg := sql.NamedArg{Name: field.StructField.DBName, Value: field.Field.Interface()} + placeholders = append(placeholders, scope.AddToVars(arg)) } } else if field.Relationship != nil && field.Relationship.Kind == "belongs_to" { for _, foreignKey := range field.Relationship.ForeignDBNames { diff --git a/scope.go b/scope.go index eb7525b8..5bda9ecf 100644 --- a/scope.go +++ b/scope.go @@ -269,7 +269,11 @@ func (scope *Scope) AddToVars(value interface{}) string { return exp } - scope.SQLVars = append(scope.SQLVars, value) + if val, ok := value.(sql.NamedArg); ok { + scope.SQLVars = append(scope.SQLVars, val.Value) + } else { + scope.SQLVars = append(scope.SQLVars, value) + } if skipBindVar { return "?" @@ -580,6 +584,14 @@ func (scope *Scope) buildCondition(clause map[string]interface{}, include bool) } } return strings.Join(sqls, " AND ") + case []sql.NamedArg: + var sqls []string + for _, val := range value { + if len(val.Name) != 0 { + sqls = append(sqls, fmt.Sprintf("(%v.%v %s %v)", quotedTableName, scope.Quote(val.Name), equalSQL, scope.AddToVars(val))) + } + } + return strings.Join(sqls, " AND ") case interface{}: var sqls []string newScope := scope.New(value) @@ -878,6 +890,14 @@ func convertInterfaceToMap(values interface{}, withIgnoredField bool, db *DB) ma switch value := values.(type) { case map[string]interface{}: return value + case []sql.NamedArg: + for _, v := range value { + for key, value := range convertInterfaceToMap(v, withIgnoredField, db) { + attrs[key] = value + } + } + case sql.NamedArg: + attrs[value.Name] = value.Value case []interface{}: for _, v := range value { for key, value := range convertInterfaceToMap(v, withIgnoredField, db) {