From db9f275317a0140633de7b432ec5164399c8b170 Mon Sep 17 00:00:00 2001 From: Aleksandr Kretov Date: Wed, 30 May 2018 21:45:54 +1000 Subject: [PATCH 1/2] Field value wrapper function feature implemented. Now you can wrap field value into user-defined wrapper function(s) with setting it using WRAPPER tag. Wrapper functions are used with INSERT/UPDATE operations to allow you to use DBMS functions when inserting/updating a field value (eg. ST_GeomFromText(?), LOWER(?), EXTRACT(YEAR FROM ?)) --- callback_create.go | 4 ++-- callback_update.go | 4 ++-- scope.go | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/callback_create.go b/callback_create.go index e7fe6f86..16dd9639 100644 --- a/callback_create.go +++ b/callback_create.go @@ -65,13 +65,13 @@ 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())) + placeholders = append(placeholders, scope.WrapPlaceholder(field, scope.AddToVars(field.Field.Interface()))) } } else if field.Relationship != nil && field.Relationship.Kind == "belongs_to" { for _, foreignKey := range field.Relationship.ForeignDBNames { if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { columns = append(columns, scope.Quote(foreignField.DBName)) - placeholders = append(placeholders, scope.AddToVars(foreignField.Field.Interface())) + placeholders = append(placeholders, scope.WrapPlaceholder(foreignField, scope.AddToVars(foreignField.Field.Interface()))) } } } diff --git a/callback_update.go b/callback_update.go index 373bd726..d8c658c6 100644 --- a/callback_update.go +++ b/callback_update.go @@ -76,12 +76,12 @@ func updateCallback(scope *Scope) { for _, field := range scope.Fields() { if scope.changeableField(field) { if !field.IsPrimaryKey && field.IsNormal { - sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) + sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.WrapPlaceholder(field, scope.AddToVars(field.Field.Interface())))) } else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { for _, foreignKey := range relationship.ForeignDBNames { if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { sqls = append(sqls, - fmt.Sprintf("%v = %v", scope.Quote(foreignField.DBName), scope.AddToVars(foreignField.Field.Interface()))) + fmt.Sprintf("%v = %v", scope.Quote(foreignField.DBName), scope.WrapPlaceholder(foreignField, scope.AddToVars(foreignField.Field.Interface())))) } } } diff --git a/scope.go b/scope.go index 397ccf0b..8557b53f 100644 --- a/scope.go +++ b/scope.go @@ -277,6 +277,16 @@ func (scope *Scope) AddToVars(value interface{}) string { return scope.Dialect().BindVar(len(scope.SQLVars)) } +// WrapPlaceholder returns a field's value placeholder wrapped into wrapper function +func (scope *Scope) WrapPlaceholder(field *Field, placeholder string) string { + if wr, exists := field.TagSettings["WRAPPER"]; !exists || len(wr) == 0 { + return placeholder + } else { + // Wrap a placeholder into wrapper + return strings.Replace(wr, "?", placeholder, 1) + } +} + // SelectAttrs return selected attributes func (scope *Scope) SelectAttrs() []string { if scope.selectAttrs == nil { From 9a35c206df28b35f1af27efd435ef7f330b29eb8 Mon Sep 17 00:00:00 2001 From: Aleksandr Kretov Date: Wed, 30 May 2018 22:07:12 +1000 Subject: [PATCH 2/2] Multiple value usage allowed within wrapper statement (eg. CONCAT(FUNC_A(?), FUNC_B(?))) --- scope.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scope.go b/scope.go index 8557b53f..4d4d3b7a 100644 --- a/scope.go +++ b/scope.go @@ -283,7 +283,7 @@ func (scope *Scope) WrapPlaceholder(field *Field, placeholder string) string { return placeholder } else { // Wrap a placeholder into wrapper - return strings.Replace(wr, "?", placeholder, 1) + return strings.Replace(wr, "?", placeholder, -1) } }