github.com/gogf/gf@v1.16.9/database/gdb/gdb_core_structure.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gdb 8 9 import ( 10 "strings" 11 "time" 12 13 "github.com/gogf/gf/util/gutil" 14 15 "github.com/gogf/gf/text/gstr" 16 17 "github.com/gogf/gf/os/gtime" 18 19 "github.com/gogf/gf/encoding/gbinary" 20 21 "github.com/gogf/gf/text/gregex" 22 "github.com/gogf/gf/util/gconv" 23 ) 24 25 // convertFieldValueToLocalValue automatically checks and converts field value from database type 26 // to golang variable type. 27 func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType string) interface{} { 28 // If there's no type retrieved, it returns the `fieldValue` directly 29 // to use its original data type, as `fieldValue` is type of interface{}. 30 if fieldType == "" { 31 return fieldValue 32 } 33 t, _ := gregex.ReplaceString(`\(.+\)`, "", fieldType) 34 t = strings.ToLower(t) 35 switch t { 36 case 37 "binary", 38 "varbinary", 39 "blob", 40 "tinyblob", 41 "mediumblob", 42 "longblob": 43 return gconv.Bytes(fieldValue) 44 45 case 46 "int", 47 "tinyint", 48 "small_int", 49 "smallint", 50 "medium_int", 51 "mediumint", 52 "serial": 53 if gstr.ContainsI(fieldType, "unsigned") { 54 gconv.Uint(gconv.String(fieldValue)) 55 } 56 return gconv.Int(gconv.String(fieldValue)) 57 58 case 59 "int8", // For pgsql, int8 = bigint. 60 "big_int", 61 "bigint", 62 "bigserial": 63 if gstr.ContainsI(fieldType, "unsigned") { 64 gconv.Uint64(gconv.String(fieldValue)) 65 } 66 return gconv.Int64(gconv.String(fieldValue)) 67 68 case "real": 69 return gconv.Float32(gconv.String(fieldValue)) 70 71 case 72 "float", 73 "double", 74 "decimal", 75 "money", 76 "numeric", 77 "smallmoney": 78 return gconv.Float64(gconv.String(fieldValue)) 79 80 case "bit": 81 s := gconv.String(fieldValue) 82 // mssql is true|false string. 83 if strings.EqualFold(s, "true") { 84 return 1 85 } 86 if strings.EqualFold(s, "false") { 87 return 0 88 } 89 return gbinary.BeDecodeToInt64(gconv.Bytes(fieldValue)) 90 91 case "bool": 92 return gconv.Bool(fieldValue) 93 94 case "date": 95 if t, ok := fieldValue.(time.Time); ok { 96 return gtime.NewFromTime(t).Format("Y-m-d") 97 } 98 t, _ := gtime.StrToTime(gconv.String(fieldValue)) 99 return t.Format("Y-m-d") 100 101 case 102 "datetime", 103 "timestamp", 104 "timestamptz": 105 if t, ok := fieldValue.(time.Time); ok { 106 return gtime.NewFromTime(t) 107 } 108 t, _ := gtime.StrToTime(gconv.String(fieldValue)) 109 return t.String() 110 111 default: 112 // Auto detect field type, using key match. 113 switch { 114 case strings.Contains(t, "text") || strings.Contains(t, "char") || strings.Contains(t, "character"): 115 return gconv.String(fieldValue) 116 117 case strings.Contains(t, "float") || strings.Contains(t, "double") || strings.Contains(t, "numeric"): 118 return gconv.Float64(gconv.String(fieldValue)) 119 120 case strings.Contains(t, "bool"): 121 return gconv.Bool(gconv.String(fieldValue)) 122 123 case strings.Contains(t, "binary") || strings.Contains(t, "blob"): 124 return fieldValue 125 126 case strings.Contains(t, "int"): 127 return gconv.Int(gconv.String(fieldValue)) 128 129 case strings.Contains(t, "time"): 130 s := gconv.String(fieldValue) 131 t, err := gtime.StrToTime(s) 132 if err != nil { 133 return s 134 } 135 return t.String() 136 137 case strings.Contains(t, "date"): 138 s := gconv.String(fieldValue) 139 t, err := gtime.StrToTime(s) 140 if err != nil { 141 return s 142 } 143 return t.Format("Y-m-d") 144 145 default: 146 return gconv.String(fieldValue) 147 } 148 } 149 } 150 151 // mappingAndFilterData automatically mappings the map key to table field and removes 152 // all key-value pairs that are not the field of given table. 153 func (c *Core) mappingAndFilterData(schema, table string, data map[string]interface{}, filter bool) (map[string]interface{}, error) { 154 if fieldsMap, err := c.db.TableFields(c.GetCtx(), table, schema); err == nil { 155 fieldsKeyMap := make(map[string]interface{}, len(fieldsMap)) 156 for k, _ := range fieldsMap { 157 fieldsKeyMap[k] = nil 158 } 159 // Automatic data key to table field name mapping. 160 var foundKey string 161 for dataKey, dataValue := range data { 162 if _, ok := fieldsKeyMap[dataKey]; !ok { 163 foundKey, _ = gutil.MapPossibleItemByKey(fieldsKeyMap, dataKey) 164 if foundKey != "" { 165 data[foundKey] = dataValue 166 delete(data, dataKey) 167 } 168 } 169 } 170 // Data filtering. 171 // It deletes all key-value pairs that has incorrect field name. 172 if filter { 173 for dataKey, _ := range data { 174 if _, ok := fieldsMap[dataKey]; !ok { 175 delete(data, dataKey) 176 } 177 } 178 } 179 } 180 return data, nil 181 } 182 183 //// filterFields removes all key-value pairs which are not the field of given table. 184 //func (c *Core) filterFields(schema, table string, data map[string]interface{}) map[string]interface{} { 185 // // It must use data copy here to avoid its changing the origin data map. 186 // newDataMap := make(map[string]interface{}, len(data)) 187 // if fields, err := c.db.TableFields(table, schema); err == nil { 188 // for k, v := range data { 189 // if _, ok := fields[k]; ok { 190 // newDataMap[k] = v 191 // } 192 // } 193 // } 194 // return newDataMap 195 //}