field.go (2659B)
1 package schema 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/uptrace/bun/dialect" 8 "github.com/uptrace/bun/internal/tagparser" 9 ) 10 11 type Field struct { 12 StructField reflect.StructField 13 IsPtr bool 14 15 Tag tagparser.Tag 16 IndirectType reflect.Type 17 Index []int 18 19 Name string // SQL name, .e.g. id 20 SQLName Safe // escaped SQL name, e.g. "id" 21 GoName string // struct field name, e.g. Id 22 23 DiscoveredSQLType string 24 UserSQLType string 25 CreateTableSQLType string 26 SQLDefault string 27 28 OnDelete string 29 OnUpdate string 30 31 IsPK bool 32 NotNull bool 33 NullZero bool 34 AutoIncrement bool 35 Identity bool 36 37 Append AppenderFunc 38 Scan ScannerFunc 39 IsZero IsZeroerFunc 40 } 41 42 func (f *Field) String() string { 43 return f.Name 44 } 45 46 func (f *Field) Clone() *Field { 47 cp := *f 48 cp.Index = cp.Index[:len(f.Index):len(f.Index)] 49 return &cp 50 } 51 52 func (f *Field) Value(strct reflect.Value) reflect.Value { 53 return fieldByIndexAlloc(strct, f.Index) 54 } 55 56 func (f *Field) HasNilValue(v reflect.Value) bool { 57 if len(f.Index) == 1 { 58 return v.Field(f.Index[0]).IsNil() 59 } 60 61 for _, index := range f.Index { 62 if v.Kind() == reflect.Ptr { 63 if v.IsNil() { 64 return true 65 } 66 v = v.Elem() 67 } 68 v = v.Field(index) 69 } 70 return v.IsNil() 71 } 72 73 func (f *Field) HasZeroValue(v reflect.Value) bool { 74 if len(f.Index) == 1 { 75 return f.IsZero(v.Field(f.Index[0])) 76 } 77 78 for _, index := range f.Index { 79 if v.Kind() == reflect.Ptr { 80 if v.IsNil() { 81 return true 82 } 83 v = v.Elem() 84 } 85 v = v.Field(index) 86 } 87 return f.IsZero(v) 88 } 89 90 func (f *Field) AppendValue(fmter Formatter, b []byte, strct reflect.Value) []byte { 91 fv, ok := fieldByIndex(strct, f.Index) 92 if !ok { 93 return dialect.AppendNull(b) 94 } 95 96 if (f.IsPtr && fv.IsNil()) || (f.NullZero && f.IsZero(fv)) { 97 return dialect.AppendNull(b) 98 } 99 if f.Append == nil { 100 panic(fmt.Errorf("bun: AppendValue(unsupported %s)", fv.Type())) 101 } 102 return f.Append(fmter, b, fv) 103 } 104 105 func (f *Field) ScanWithCheck(fv reflect.Value, src interface{}) error { 106 if f.Scan == nil { 107 return fmt.Errorf("bun: Scan(unsupported %s)", f.IndirectType) 108 } 109 return f.Scan(fv, src) 110 } 111 112 func (f *Field) ScanValue(strct reflect.Value, src interface{}) error { 113 if src == nil { 114 if fv, ok := fieldByIndex(strct, f.Index); ok { 115 return f.ScanWithCheck(fv, src) 116 } 117 return nil 118 } 119 120 fv := fieldByIndexAlloc(strct, f.Index) 121 return f.ScanWithCheck(fv, src) 122 } 123 124 func (f *Field) SkipUpdate() bool { 125 return f.Tag.HasOption("skipupdate") 126 } 127 128 func indexEqual(ind1, ind2 []int) bool { 129 if len(ind1) != len(ind2) { 130 return false 131 } 132 for i, ind := range ind1 { 133 if ind != ind2[i] { 134 return false 135 } 136 } 137 return true 138 }