package sqlite3 import ( "database/sql" "regexp" "time" "git.fsdpf.net/go/db" "git.fsdpf.net/go/db/exp" gosqlite3 "github.com/mattn/go-sqlite3" ) // DriverWithIF 是注册了 IF() 函数的 SQLite3 驱动名称。 // 使用该驱动名打开连接时,可在 SQL 中直接使用 IF(condition, trueVal, falseVal)。 const DriverWithIF = "sqlite3_with_if" func DialectOptions() *db.SQLDialectOptions { opts := db.DefaultDialectOptions() opts.SupportsReturn = true opts.SupportsOrderByOnUpdate = true opts.SupportsLimitOnUpdate = true opts.SupportsOrderByOnDelete = true opts.SupportsLimitOnDelete = true opts.SupportsConflictUpdateWhere = false opts.SupportsInsertIgnoreSyntax = true opts.SupportsConflictTarget = true opts.SupportsMultipleUpdateTables = false opts.WrapCompoundsInParens = false opts.SupportsDistinct = true // 设为 false 可全局禁止生成 DISTINCT 关键字 opts.SupportsDistinctOn = false opts.SupportsWindowFunction = false opts.SupportsLateral = false opts.PlaceHolderFragment = []byte("?") opts.IncludePlaceholderNum = false opts.QuoteRune = '`' opts.DefaultValuesFragment = []byte("") opts.True = []byte("1") opts.False = []byte("0") opts.TimeFormat = time.RFC3339Nano opts.BooleanOperatorLookup = map[exp.BooleanOperation][]byte{ exp.EqOp: []byte("="), exp.NeqOp: []byte("!="), exp.GtOp: []byte(">"), exp.GteOp: []byte(">="), exp.LtOp: []byte("<"), exp.LteOp: []byte("<="), exp.InOp: []byte("IN"), exp.NotInOp: []byte("NOT IN"), exp.IsOp: []byte("IS"), exp.IsNotOp: []byte("IS NOT"), exp.LikeOp: []byte("LIKE"), exp.NotLikeOp: []byte("NOT LIKE"), exp.ILikeOp: []byte("LIKE"), exp.NotILikeOp: []byte("NOT LIKE"), exp.RegexpLikeOp: []byte("REGEXP"), exp.RegexpNotLikeOp: []byte("NOT REGEXP"), exp.RegexpILikeOp: []byte("REGEXP"), exp.RegexpNotILikeOp: []byte("NOT REGEXP"), } opts.UseLiteralIsBools = false opts.BitwiseOperatorLookup = map[exp.BitwiseOperation][]byte{ exp.BitwiseOrOp: []byte("|"), exp.BitwiseAndOp: []byte("&"), exp.BitwiseLeftShiftOp: []byte("<<"), exp.BitwiseRightShiftOp: []byte(">>"), } opts.EscapedRunes = map[rune][]byte{ '\'': []byte("''"), } opts.InsertIgnoreClause = []byte("INSERT OR IGNORE INTO ") opts.ConflictFragment = []byte(" ON CONFLICT ") opts.ConflictDoUpdateFragment = []byte(" DO UPDATE SET ") opts.ConflictDoNothingFragment = []byte(" DO NOTHING ") opts.ForUpdateFragment = []byte("") opts.OfFragment = []byte("") opts.NowaitFragment = []byte("") return opts } func init() { sql.Register(DriverWithIF, &gosqlite3.SQLiteDriver{ ConnectHook: func(conn *gosqlite3.SQLiteConn) error { if err := conn.RegisterFunc("IF", func(cond int64, trueVal, falseVal interface{}) interface{} { if cond != 0 { return trueVal } return falseVal }, true); err != nil { return err } if err := conn.RegisterFunc("REGEXP", func(expr, item string) (bool, error) { return regexp.MatchString(expr, item) }, true); err != nil { return err } return nil }, }) db.RegisterDialect("sqlite3", DialectOptions()) }