github.com/gogf/gf@v1.16.9/database/gdb/gdb_driver_sqlite.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 // Note: 8 // 1. It needs manually import: _ "github.com/mattn/go-sqlite3" 9 // 2. It does not support Save/Replace features. 10 11 package gdb 12 13 import ( 14 "context" 15 "database/sql" 16 "fmt" 17 "github.com/gogf/gf/errors/gcode" 18 "strings" 19 20 "github.com/gogf/gf/errors/gerror" 21 "github.com/gogf/gf/internal/intlog" 22 "github.com/gogf/gf/os/gfile" 23 "github.com/gogf/gf/text/gstr" 24 ) 25 26 // DriverSqlite is the driver for sqlite database. 27 type DriverSqlite struct { 28 *Core 29 } 30 31 // New creates and returns a database object for sqlite. 32 // It implements the interface of gdb.Driver for extra database driver installation. 33 func (d *DriverSqlite) New(core *Core, node *ConfigNode) (DB, error) { 34 return &DriverSqlite{ 35 Core: core, 36 }, nil 37 } 38 39 // Open creates and returns a underlying sql.DB object for sqlite. 40 func (d *DriverSqlite) Open(config *ConfigNode) (*sql.DB, error) { 41 var source string 42 if config.Link != "" { 43 source = config.Link 44 } else { 45 source = config.Name 46 } 47 // It searches the source file to locate its absolute path.. 48 if absolutePath, _ := gfile.Search(source); absolutePath != "" { 49 source = absolutePath 50 } 51 intlog.Printf(d.GetCtx(), "Open: %s", source) 52 if db, err := sql.Open("sqlite3", source); err == nil { 53 return db, nil 54 } else { 55 return nil, err 56 } 57 } 58 59 // FilteredLink retrieves and returns filtered `linkInfo` that can be using for 60 // logging or tracing purpose. 61 func (d *DriverSqlite) FilteredLink() string { 62 return d.GetConfig().Link 63 } 64 65 // GetChars returns the security char for this type of database. 66 func (d *DriverSqlite) GetChars() (charLeft string, charRight string) { 67 return "`", "`" 68 } 69 70 // DoCommit deals with the sql string before commits it to underlying sql driver. 71 func (d *DriverSqlite) DoCommit(ctx context.Context, link Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { 72 return d.Core.DoCommit(ctx, link, sql, args) 73 } 74 75 // Tables retrieves and returns the tables of current schema. 76 // It's mainly used in cli tool chain for automatically generating the models. 77 func (d *DriverSqlite) Tables(ctx context.Context, schema ...string) (tables []string, err error) { 78 var result Result 79 link, err := d.SlaveLink(schema...) 80 if err != nil { 81 return nil, err 82 } 83 84 result, err = d.DoGetAll(ctx, link, `SELECT NAME FROM SQLITE_MASTER WHERE TYPE='table' ORDER BY NAME`) 85 if err != nil { 86 return 87 } 88 for _, m := range result { 89 for _, v := range m { 90 tables = append(tables, v.String()) 91 } 92 } 93 return 94 } 95 96 // TableFields retrieves and returns the fields information of specified table of current schema. 97 // 98 // Also see DriverMysql.TableFields. 99 func (d *DriverSqlite) TableFields(ctx context.Context, table string, schema ...string) (fields map[string]*TableField, err error) { 100 charL, charR := d.GetChars() 101 table = gstr.Trim(table, charL+charR) 102 if gstr.Contains(table, " ") { 103 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "function TableFields supports only single table operations") 104 } 105 useSchema := d.db.GetSchema() 106 if len(schema) > 0 && schema[0] != "" { 107 useSchema = schema[0] 108 } 109 tableFieldsCacheKey := fmt.Sprintf( 110 `sqlite_table_fields_%s_%s@group:%s`, 111 table, useSchema, d.GetGroup(), 112 ) 113 v := tableFieldsMap.GetOrSetFuncLock(tableFieldsCacheKey, func() interface{} { 114 var ( 115 result Result 116 link, err = d.SlaveLink(useSchema) 117 ) 118 if err != nil { 119 return nil 120 } 121 result, err = d.DoGetAll(ctx, link, fmt.Sprintf(`PRAGMA TABLE_INFO(%s)`, table)) 122 if err != nil { 123 return nil 124 } 125 fields = make(map[string]*TableField) 126 for i, m := range result { 127 fields[strings.ToLower(m["name"].String())] = &TableField{ 128 Index: i, 129 Name: strings.ToLower(m["name"].String()), 130 Type: strings.ToLower(m["type"].String()), 131 } 132 } 133 return fields 134 }) 135 if v != nil { 136 fields = v.(map[string]*TableField) 137 } 138 return 139 } 140 141 // DoInsert is not supported in sqlite. 142 func (d *DriverSqlite) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { 143 switch option.InsertOption { 144 case insertOptionSave: 145 return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`) 146 147 case insertOptionReplace: 148 return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by sqlite driver`) 149 150 default: 151 return d.Core.DoInsert(ctx, link, table, list, option) 152 } 153 }