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  }