本文作者:icy

Golang-sqlite 自定义函数注册使用

icy 10-13 52 抢沙发
Golang-sqlite 自定义函数注册使用摘要: 在一些场景中我们必要使用在sqlite查询中好用的函数,这样更加方便,更加好用,嘿嘿比如下面将给出的例子中我们获取一个字符串的MD5值是很常见的。如果返回结果要加上这个计算好的值,...

在一些场景中我们必要使用在sqlite查询中好用的函数,

这样更加方便,更加好用,嘿嘿

比如下面将给出的例子中我们获取一个字符串的MD5值是很常见的。

如果返回结果要加上这个计算好的值,需要在结果集内一一处理。

下面我们就开始使用。首先要用到一个golang的第三方包:

go get -u github.com/mattn/go-sqlite3
#  sqlite3 "github.com/mattn/go-sqlite3"

golang 的标准库 数据库 database/sql

有一个 sql.Register

下面就看看注册函数的完整使用例子

sql.Register("sqlite3_extended",
	&sqlite3.SQLiteDriver{
		ConnectHook: func(sc *sqlite3.SQLiteConn) error {
			return sc.RegisterFunc("md5", MD5, true)
		},
	})

其中这里用到的 go-sqlite3 这个库中的 ConnectHook 连接钩子

然后我们家可以使用了 标准库sql查询的例子:

db, err := sql.Open("sqlite3_extended", ":memory:")
if err != nil {
    fmt.Println(err.Error())
}
defer db.Close()


err = db.QueryRow("SELECT md5('hello world')").Scan(&result)
if err != nil {
    fmt.Println(err.Error())
}


这里我们主要看看 ConnectHook 这个函数的相关说明:

这个绑定回调你的函数支持的返回类型 SQLite 数据 → Go 类型(只有这些,不能用 time.Time、struct 等):

INTEGER  → int64
FLOAT    → float64
TEXT     → string
BLOB     → []byte
NULL     → nil(以 interface{} 形式传进来)

允许的形式:
普通函数:        func f(a, b string) float64
变参函数:        func f(vals ...int64) int64

接收 interface{}:func f(args ...interface{}) interface{}


sqlite3.SQLiteConn.RegisterFunc 说明

  1. 注册函数名

  2. 函数体

  3. pure

    pure = true    SQLite 认为“相同输入一定相同输出”,可缓存结果,查询更激进优化。在 CHECK 约束、部分索引里必须用纯函数。

    pure = false 每次调用都重新计算(如含随机数、读文件、时间等)。下面看一个完整的实例 使用了标准库和GORM的例子:

package main

/*
   这个例子展示了如何在 SQLite 中注册并使用自定义的 MD5 函数。
   我们使用:github.com/mattn/go-sqlite3
   通过在连接钩子中注册自定义函数,我们可以在 SQL 查询中调用该函数。

   注意:确保你已经安装了所需的包:
   go get github.com/mattn/go-sqlite3
   go get gorm.io/gorm
   go get gorm.io/driver/sqlite
   go get github.com/glebarez/sqlite

   author: icy
   blog: https://zelig.cn
*/

import (
    "crypto/md5"
    "database/sql"
    "encoding/hex"
    "fmt"

    sdb "github.com/glebarez/sqlite"
    sqlite3 "github.com/mattn/go-sqlite3"
    "gorm.io/gorm"
)

func main() {
    // 注册自定义的 MD5 函数
    MD5 := func(str string) string {
        _md5 := md5.New()
        _md5.Write([]byte(str))
        return hex.EncodeToString(_md5.Sum([]byte("")))
    }

    sql.Register("sqlite3_extended", // 注册自定义驱动名
        &sqlite3.SQLiteDriver{
            /// 这里是连接钩子,用于在每次数据库连接时注册自定义函数
            ConnectHook: func(sc *sqlite3.SQLiteConn) error {
                return sc.RegisterFunc("md5", MD5, true)
            },
        })

    var result string
    /*
        // 使用标准库打开数据库连接
            db, err := sql.Open("sqlite3_extended", ":memory:")
            if err != nil {
                fmt.Println(err.Error())
            }
            defer db.Close()


            err = db.QueryRow("SELECT md5('hello world')").Scan(&result)
            if err != nil {
                fmt.Println(err.Error())
            }
    */

    // 使用 GORM 打开数据库连接 设置驱动名和 DSN - 主要是驱动名要和上面注册的保持一致
    db, err := gorm.Open(sdb.Dialector{DriverName: "sqlite3_extended",
        DSN: "test.db"}, &gorm.Config{})
    if err != nil {
        fmt.Println(err.Error())
    }

    db.Raw("select md5('hello world')").Scan(&result)

    fmt.Println(result)
}

运行返回:

Golang-sqlite 自定义函数注册使用


好了你可以 开发一个包 把一些常用的注册到函数 写到一起了。

如果你不想开发。还有更懒的做法:

sql.Register("sqlite3_ext",
&sqlite3.SQLiteDriver{
    Extensions: []string{
        "...",
    },
})

使用扩展包

扩展包可以 从 https://sqlpkg.org/all/ 获取。linux/MacOS/Windows 系统下载对应的即可

也可以下载 sqlpkg 工具 使用命令

sqlpkg install asg017/lines


文章版权及转载声明

作者:icy本文地址:https://zelig.cn/2025/10/133.html发布于 10-13
文章转载或复制请以超链接形式并注明出处软角落-SoftNook

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

阅读
分享

发表评论

快捷回复:

验证码

评论列表 (暂无评论,52人围观)参与讨论

还没有评论,来说两句吧...