package gormlite
import (
"strconv"
"gorm.io/gorm"
"gorm.io/gorm/callbacks"
"gorm.io/gorm/clause"
"gorm.io/gorm/logger"
"gorm.io/gorm/migrator"
"gorm.io/gorm/schema"
"github.com/ncruces/go-sqlite3/driver"
)
type _Dialector struct {
DSN string
Conn gorm .ConnPool
}
func Open (dsn string ) gorm .Dialector {
return &_Dialector {DSN : dsn }
}
func OpenDB (db gorm .ConnPool ) gorm .Dialector {
return &_Dialector {Conn : db }
}
func (dialector _Dialector ) Name () string {
return "sqlite"
}
func (dialector _Dialector ) Initialize (db *gorm .DB ) (err error ) {
if dialector .Conn != nil {
db .ConnPool = dialector .Conn
} else {
conn , err := driver .Open (dialector .DSN )
if err != nil {
return err
}
db .ConnPool = conn
}
callbacks .RegisterDefaultCallbacks (db , &callbacks .Config {
CreateClauses : []string {"INSERT" , "VALUES" , "ON CONFLICT" , "RETURNING" },
UpdateClauses : []string {"UPDATE" , "SET" , "FROM" , "WHERE" , "RETURNING" },
DeleteClauses : []string {"DELETE" , "FROM" , "WHERE" , "RETURNING" },
LastInsertIDReversed : true ,
})
for k , v := range dialector .ClauseBuilders () {
db .ClauseBuilders [k ] = v
}
return
}
func (dialector _Dialector ) ClauseBuilders () map [string ]clause .ClauseBuilder {
return map [string ]clause .ClauseBuilder {
"INSERT" : func (c clause .Clause , builder clause .Builder ) {
if insert , ok := c .Expression .(clause .Insert ); ok {
if stmt , ok := builder .(*gorm .Statement ); ok {
stmt .WriteString ("INSERT " )
if insert .Modifier != "" {
stmt .WriteString (insert .Modifier )
stmt .WriteByte (' ' )
}
stmt .WriteString ("INTO " )
if insert .Table .Name == "" {
stmt .WriteQuoted (stmt .Table )
} else {
stmt .WriteQuoted (insert .Table )
}
return
}
}
c .Build (builder )
},
"LIMIT" : func (c clause .Clause , builder clause .Builder ) {
if limit , ok := c .Expression .(clause .Limit ); ok {
var lmt = -1
if limit .Limit != nil && *limit .Limit >= 0 {
lmt = *limit .Limit
}
if lmt >= 0 || limit .Offset > 0 {
builder .WriteString ("LIMIT " )
builder .WriteString (strconv .Itoa (lmt ))
}
if limit .Offset > 0 {
builder .WriteString (" OFFSET " )
builder .WriteString (strconv .Itoa (limit .Offset ))
}
}
},
"FOR" : func (c clause .Clause , builder clause .Builder ) {
if _ , ok := c .Expression .(clause .Locking ); ok {
return
}
c .Build (builder )
},
}
}
func (dialector _Dialector ) DefaultValueOf (field *schema .Field ) clause .Expression {
if field .AutoIncrement {
return clause .Expr {SQL : "NULL" }
}
return clause .Expr {SQL : "DEFAULT" }
}
func (dialector _Dialector ) Migrator (db *gorm .DB ) gorm .Migrator {
return _Migrator {migrator .Migrator {Config : migrator .Config {
DB : db ,
Dialector : dialector ,
CreateIndexAfterCreateTable : true ,
}}}
}
func (dialector _Dialector ) BindVarTo (writer clause .Writer , stmt *gorm .Statement , v interface {}) {
writer .WriteByte ('?' )
}
func (dialector _Dialector ) QuoteTo (writer clause .Writer , str string ) {
var (
underQuoted , selfQuoted bool
continuousBacktick int8
shiftDelimiter int8
)
for _ , v := range []byte (str ) {
switch v {
case '`' :
continuousBacktick ++
if continuousBacktick == 2 {
writer .WriteString ("``" )
continuousBacktick = 0
}
case '.' :
if continuousBacktick > 0 || !selfQuoted {
shiftDelimiter = 0
underQuoted = false
continuousBacktick = 0
writer .WriteString ("`" )
}
writer .WriteByte (v )
continue
default :
if shiftDelimiter -continuousBacktick <= 0 && !underQuoted {
writer .WriteString ("`" )
underQuoted = true
if selfQuoted = continuousBacktick > 0 ; selfQuoted {
continuousBacktick -= 1
}
}
for ; continuousBacktick > 0 ; continuousBacktick -= 1 {
writer .WriteString ("``" )
}
writer .WriteByte (v )
}
shiftDelimiter ++
}
if continuousBacktick > 0 && !selfQuoted {
writer .WriteString ("``" )
}
writer .WriteString ("`" )
}
func (dialector _Dialector ) Explain (sql string , vars ...interface {}) string {
return logger .ExplainSQL (sql , nil , `"` , vars ...)
}
func (dialector _Dialector ) DataTypeOf (field *schema .Field ) string {
switch field .DataType {
case schema .Bool :
return "numeric"
case schema .Int , schema .Uint :
if field .AutoIncrement {
return "integer PRIMARY KEY AUTOINCREMENT"
} else {
return "integer"
}
case schema .Float :
return "real"
case schema .String :
return "text"
case schema .Time :
if val , ok := field .TagSettings ["TYPE" ]; ok {
return val
} else {
return "datetime"
}
case schema .Bytes :
return "blob"
}
return string (field .DataType )
}
func (dialectopr _Dialector ) SavePoint (tx *gorm .DB , name string ) error {
tx .Exec ("SAVEPOINT " + name )
return nil
}
func (dialectopr _Dialector ) RollbackTo (tx *gorm .DB , name string ) error {
tx .Exec ("ROLLBACK TO SAVEPOINT " + name )
return nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .