github.com/wangyougui/gf/v2@v2.6.5/database/gdb/gdb_driver_wrapper_db.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/wangyougui/gf. 6 7 package gdb 8 9 import ( 10 "context" 11 "database/sql" 12 "fmt" 13 14 "github.com/wangyougui/gf/v2/encoding/gjson" 15 "github.com/wangyougui/gf/v2/errors/gcode" 16 "github.com/wangyougui/gf/v2/errors/gerror" 17 "github.com/wangyougui/gf/v2/internal/intlog" 18 "github.com/wangyougui/gf/v2/text/gstr" 19 "github.com/wangyougui/gf/v2/util/gutil" 20 ) 21 22 // DriverWrapperDB is a DB wrapper for extending features with embedded DB. 23 type DriverWrapperDB struct { 24 DB 25 } 26 27 // Open creates and returns an underlying sql.DB object for pgsql. 28 // https://pkg.go.dev/github.com/lib/pq 29 func (d *DriverWrapperDB) Open(node *ConfigNode) (db *sql.DB, err error) { 30 var ctx = d.GetCtx() 31 intlog.PrintFunc(ctx, func() string { 32 return fmt.Sprintf(`open new connection:%s`, gjson.MustEncode(node)) 33 }) 34 return d.DB.Open(node) 35 } 36 37 // Tables retrieves and returns the tables of current schema. 38 // It's mainly used in cli tool chain for automatically generating the models. 39 func (d *DriverWrapperDB) Tables(ctx context.Context, schema ...string) (tables []string, err error) { 40 ctx = context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}) 41 return d.DB.Tables(ctx, schema...) 42 } 43 44 // TableFields retrieves and returns the fields' information of specified table of current 45 // schema. 46 // 47 // The parameter `link` is optional, if given nil it automatically retrieves a raw sql connection 48 // as its link to proceed necessary sql query. 49 // 50 // Note that it returns a map containing the field name and its corresponding fields. 51 // As a map is unsorted, the TableField struct has an "Index" field marks its sequence in 52 // the fields. 53 // 54 // It's using cache feature to enhance the performance, which is never expired util the 55 // process restarts. 56 func (d *DriverWrapperDB) TableFields( 57 ctx context.Context, table string, schema ...string, 58 ) (fields map[string]*TableField, err error) { 59 if table == "" { 60 return nil, nil 61 } 62 charL, charR := d.GetChars() 63 table = gstr.Trim(table, charL+charR) 64 if gstr.Contains(table, " ") { 65 return nil, gerror.NewCode( 66 gcode.CodeInvalidParameter, 67 "function TableFields supports only single table operations", 68 ) 69 } 70 var ( 71 // prefix:group@schema#table 72 cacheKey = fmt.Sprintf( 73 `%s%s@%s#%s`, 74 cachePrefixTableFields, 75 d.GetGroup(), 76 gutil.GetOrDefaultStr(d.GetSchema(), schema...), 77 table, 78 ) 79 value = tableFieldsMap.GetOrSetFuncLock(cacheKey, func() interface{} { 80 ctx = context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}) 81 fields, err = d.DB.TableFields(ctx, table, schema...) 82 if err != nil { 83 return nil 84 } 85 return fields 86 }) 87 ) 88 if value != nil { 89 fields = value.(map[string]*TableField) 90 } 91 return 92 } 93 94 // DoInsert inserts or updates data for given table. 95 // This function is usually used for custom interface definition, you do not need call it manually. 96 // The parameter `data` can be type of map/gmap/struct/*struct/[]map/[]struct, etc. 97 // Eg: 98 // Data(g.Map{"uid": 10000, "name":"john"}) 99 // Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) 100 // 101 // The parameter `option` values are as follows: 102 // InsertOptionDefault: just insert, if there's unique/primary key in the data, it returns error; 103 // InsertOptionReplace: if there's unique/primary key in the data, it deletes it from table and inserts a new one; 104 // InsertOptionSave: if there's unique/primary key in the data, it updates it or else inserts a new one; 105 // InsertOptionIgnore: if there's unique/primary key in the data, it ignores the inserting; 106 func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { 107 // Convert data type before commit it to underlying db driver. 108 for i, item := range list { 109 list[i], err = d.GetCore().ConvertDataForRecord(ctx, item, table) 110 if err != nil { 111 return nil, err 112 } 113 } 114 return d.DB.DoInsert(ctx, link, table, list, option) 115 }