hstore.go (1513B)
1 package pgdialect 2 3 import ( 4 "database/sql" 5 "fmt" 6 "reflect" 7 8 "github.com/uptrace/bun/schema" 9 ) 10 11 type HStoreValue struct { 12 v reflect.Value 13 14 append schema.AppenderFunc 15 scan schema.ScannerFunc 16 } 17 18 // HStore accepts a map[string]string and returns a wrapper for working with PostgreSQL 19 // hstore data type. 20 // 21 // For struct fields you can use hstore tag: 22 // 23 // Attrs map[string]string `bun:",hstore"` 24 func HStore(vi interface{}) *HStoreValue { 25 v := reflect.ValueOf(vi) 26 if !v.IsValid() { 27 panic(fmt.Errorf("bun: HStore(nil)")) 28 } 29 30 typ := v.Type() 31 if typ.Kind() == reflect.Ptr { 32 typ = typ.Elem() 33 } 34 if typ.Kind() != reflect.Map { 35 panic(fmt.Errorf("bun: Hstore(unsupported %s)", typ)) 36 } 37 38 return &HStoreValue{ 39 v: v, 40 41 append: pgDialect.hstoreAppender(v.Type()), 42 scan: hstoreScanner(v.Type()), 43 } 44 } 45 46 var ( 47 _ schema.QueryAppender = (*HStoreValue)(nil) 48 _ sql.Scanner = (*HStoreValue)(nil) 49 ) 50 51 func (h *HStoreValue) AppendQuery(fmter schema.Formatter, b []byte) ([]byte, error) { 52 if h.append == nil { 53 panic(fmt.Errorf("bun: HStore(unsupported %s)", h.v.Type())) 54 } 55 return h.append(fmter, b, h.v), nil 56 } 57 58 func (h *HStoreValue) Scan(src interface{}) error { 59 if h.scan == nil { 60 return fmt.Errorf("bun: HStore(unsupported %s)", h.v.Type()) 61 } 62 if h.v.Kind() != reflect.Ptr { 63 return fmt.Errorf("bun: HStore(non-pointer %s)", h.v.Type()) 64 } 65 return h.scan(h.v.Elem(), src) 66 } 67 68 func (h *HStoreValue) Value() interface{} { 69 if h.v.IsValid() { 70 return h.v.Interface() 71 } 72 return nil 73 }