github.com/systematiccaos/gorm@v1.22.6/callbacks/helper.go (about)

     1  package callbacks
     2  
     3  import (
     4  	"sort"
     5  
     6  	"github.com/systematiccaos/gorm"
     7  	"github.com/systematiccaos/gorm/clause"
     8  )
     9  
    10  // ConvertMapToValuesForCreate convert map to values
    11  func ConvertMapToValuesForCreate(stmt *gorm.Statement, mapValue map[string]interface{}) (values clause.Values) {
    12  	values.Columns = make([]clause.Column, 0, len(mapValue))
    13  	selectColumns, restricted := stmt.SelectAndOmitColumns(true, false)
    14  
    15  	var keys = make([]string, 0, len(mapValue))
    16  	for k := range mapValue {
    17  		keys = append(keys, k)
    18  	}
    19  	sort.Strings(keys)
    20  
    21  	for _, k := range keys {
    22  		value := mapValue[k]
    23  		if stmt.Schema != nil {
    24  			if field := stmt.Schema.LookUpField(k); field != nil {
    25  				k = field.DBName
    26  			}
    27  		}
    28  
    29  		if v, ok := selectColumns[k]; (ok && v) || (!ok && !restricted) {
    30  			values.Columns = append(values.Columns, clause.Column{Name: k})
    31  			if len(values.Values) == 0 {
    32  				values.Values = [][]interface{}{{}}
    33  			}
    34  
    35  			values.Values[0] = append(values.Values[0], value)
    36  		}
    37  	}
    38  	return
    39  }
    40  
    41  // ConvertSliceOfMapToValuesForCreate convert slice of map to values
    42  func ConvertSliceOfMapToValuesForCreate(stmt *gorm.Statement, mapValues []map[string]interface{}) (values clause.Values) {
    43  	var (
    44  		columns = make([]string, 0, len(mapValues))
    45  	)
    46  
    47  	// when the length of mapValues is zero,return directly here
    48  	// no need to call stmt.SelectAndOmitColumns method
    49  	if len(mapValues) == 0 {
    50  		stmt.AddError(gorm.ErrEmptySlice)
    51  		return
    52  	}
    53  
    54  	var (
    55  		result                    = make(map[string][]interface{}, len(mapValues))
    56  		selectColumns, restricted = stmt.SelectAndOmitColumns(true, false)
    57  	)
    58  
    59  	for idx, mapValue := range mapValues {
    60  		for k, v := range mapValue {
    61  			if stmt.Schema != nil {
    62  				if field := stmt.Schema.LookUpField(k); field != nil {
    63  					k = field.DBName
    64  				}
    65  			}
    66  
    67  			if _, ok := result[k]; !ok {
    68  				if v, ok := selectColumns[k]; (ok && v) || (!ok && !restricted) {
    69  					result[k] = make([]interface{}, len(mapValues))
    70  					columns = append(columns, k)
    71  				} else {
    72  					continue
    73  				}
    74  			}
    75  
    76  			result[k][idx] = v
    77  		}
    78  	}
    79  
    80  	sort.Strings(columns)
    81  	values.Values = make([][]interface{}, len(mapValues))
    82  	values.Columns = make([]clause.Column, len(columns))
    83  	for idx, column := range columns {
    84  		values.Columns[idx] = clause.Column{Name: column}
    85  
    86  		for i, v := range result[column] {
    87  			if len(values.Values[i]) == 0 {
    88  				values.Values[i] = make([]interface{}, len(columns))
    89  			}
    90  
    91  			values.Values[i][idx] = v
    92  		}
    93  	}
    94  	return
    95  }
    96  
    97  func hasReturning(tx *gorm.DB, supportReturning bool) (bool, gorm.ScanMode) {
    98  	if supportReturning {
    99  		if c, ok := tx.Statement.Clauses["RETURNING"]; ok {
   100  			returning, _ := c.Expression.(clause.Returning)
   101  			if len(returning.Columns) == 0 || (len(returning.Columns) == 1 && returning.Columns[0].Name == "*") {
   102  				return true, 0
   103  			}
   104  			return true, gorm.ScanUpdate
   105  		}
   106  	}
   107  	return false, 0
   108  }