package callbacks
import (
"reflect"
"sort"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func ConvertMapToValuesForCreate (stmt *gorm .Statement , mapValue map [string ]interface {}) (values clause .Values ) {
values .Columns = make ([]clause .Column , 0 , len (mapValue ))
selectColumns , restricted := stmt .SelectAndOmitColumns (true , false )
keys := make ([]string , 0 , len (mapValue ))
for k := range mapValue {
keys = append (keys , k )
}
sort .Strings (keys )
for _ , k := range keys {
value := mapValue [k ]
if stmt .Schema != nil {
if field := stmt .Schema .LookUpField (k ); field != nil {
k = field .DBName
}
}
if v , ok := selectColumns [k ]; (ok && v ) || (!ok && !restricted ) {
values .Columns = append (values .Columns , clause .Column {Name : k })
if len (values .Values ) == 0 {
values .Values = [][]interface {}{{}}
}
values .Values [0 ] = append (values .Values [0 ], value )
}
}
return
}
func ConvertSliceOfMapToValuesForCreate (stmt *gorm .Statement , mapValues []map [string ]interface {}) (values clause .Values ) {
columns := make ([]string , 0 , len (mapValues ))
if len (mapValues ) == 0 {
stmt .AddError (gorm .ErrEmptySlice )
return
}
var (
result = make (map [string ][]interface {}, len (mapValues ))
selectColumns , restricted = stmt .SelectAndOmitColumns (true , false )
)
for idx , mapValue := range mapValues {
for k , v := range mapValue {
if stmt .Schema != nil {
if field := stmt .Schema .LookUpField (k ); field != nil {
k = field .DBName
}
}
if _ , ok := result [k ]; !ok {
if v , ok := selectColumns [k ]; (ok && v ) || (!ok && !restricted ) {
result [k ] = make ([]interface {}, len (mapValues ))
columns = append (columns , k )
} else {
continue
}
}
result [k ][idx ] = v
}
}
sort .Strings (columns )
values .Values = make ([][]interface {}, len (mapValues ))
values .Columns = make ([]clause .Column , len (columns ))
for idx , column := range columns {
values .Columns [idx ] = clause .Column {Name : column }
for i , v := range result [column ] {
if len (values .Values [i ]) == 0 {
values .Values [i ] = make ([]interface {}, len (columns ))
}
values .Values [i ][idx ] = v
}
}
return
}
func hasReturning(tx *gorm .DB , supportReturning bool ) (bool , gorm .ScanMode ) {
if supportReturning {
if c , ok := tx .Statement .Clauses ["RETURNING" ]; ok {
returning , _ := c .Expression .(clause .Returning )
if len (returning .Columns ) == 0 || (len (returning .Columns ) == 1 && returning .Columns [0 ].Name == "*" ) {
return true , 0
}
return true , gorm .ScanUpdate
}
}
return false , 0
}
func checkMissingWhereConditions(db *gorm .DB ) {
if !db .AllowGlobalUpdate && db .Error == nil {
where , withCondition := db .Statement .Clauses ["WHERE" ]
if withCondition {
if _ , withSoftDelete := db .Statement .Clauses ["soft_delete_enabled" ]; withSoftDelete {
whereClause , _ := where .Expression .(clause .Where )
withCondition = len (whereClause .Exprs ) > 1
}
}
if !withCondition {
db .AddError (gorm .ErrMissingWhereClause )
}
return
}
}
type visitMap = map [reflect .Value ]bool
func loadOrStoreVisitMap(visitMap *visitMap , v reflect .Value ) (loaded bool ) {
if v .Kind () == reflect .Ptr {
v = v .Elem ()
}
switch v .Kind () {
case reflect .Slice , reflect .Array :
loaded = true
for i := 0 ; i < v .Len (); i ++ {
if !loadOrStoreVisitMap (visitMap , v .Index (i )) {
loaded = false
}
}
case reflect .Struct , reflect .Interface :
if v .CanAddr () {
p := v .Addr ()
if _ , ok := (*visitMap )[p ]; ok {
return true
}
(*visitMap )[p ] = true
}
}
return
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .