KSQL的创建目的是为Golang提供一个真正简单且令人满意的SQL数据库交互工具。
KSQL的核心目标不是提供其他库没有的新功能(尽管我们确实有一些),而是提供一个经过深思熟虑和精心设计的API,让用户更容易学习、调试和避免常见陷阱。
KSQL还与其后端解耦,因此与数据库的实际通信是由知名且值得信赖的技术(即pgx
和database/sql
)执行的。在某些情况下,你甚至可以为KSQL创建自己的后端适配器。
在本README中,你将找到库的"入门"示例,对于更高级的用例,请阅读我们的Wiki。
database/sql
和pgx
sql.Scanner
和sql.Valuer
以及所有pgx
特殊类型(使用kpgx
时)以下简短示例是一个TLDR版本,用于说明使用KSQL有多容易。
你将在下面的章节中找到更完整的示例。
package main import ( "context" "fmt" "log" "os" "github.com/vingarcia/ksql" "github.com/vingarcia/ksql/adapters/kpgx" ) var UsersTable = ksql.NewTable("users", "user_id") type User struct { ID int `ksql:"user_id"` Name string `ksql:"name"` Type string `ksql:"type"` } func main() { ctx := context.Background() db, err := kpgx.New(ctx, os.Getenv("POSTGRES_URL"), ksql.Config{}) if err != nil { log.Fatalf("无法连接到数据库:%s", err) } defer db.Close() // 要只查询某些属性,你可以 // 创建一个自定义结构体,像这样: var count []struct { Count string `ksql:"count"` Type string `ksql:"type"` } err = db.Query(ctx, &count, "SELECT type, count(*) as count FROM users WHERE type = $1 GROUP BY type", "admin") if err != nil { log.Fatalf("无法查询用户:%s", err) } fmt.Println("按类型的用户数量:", count) // 对于从数据库加载实体,如果你省略SELECT部分,KSQL可以为你构建查询,像这样: var users []User err = db.Query(ctx, &users, "FROM users WHERE type = $1", "admin") if err != nil { log.Fatalf("无法查询用户:%s", err) } fmt.Println("用户:", users) }
我们支持几种不同的适配器,其中一个在上面有说明(kpgx
),其他适配器有完全相同的签名,但适用于不同的数据库或驱动程序版本,它们是:
kpgx.New(ctx, os.Getenv("DATABASE_URL"), ksql.Config{})
用于Postgres,它基于pgxpool
和pgx版本4,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/kpgx
kpgx5.New(ctx, os.Getenv("DATABASE_URL"), ksql.Config{})
用于Postgres,它基于pgxpool
和pgx版本5,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/kpgx5
kmysql.New(ctx, os.Getenv("DATABASE_URL"), ksql.Config{})
用于MySQL,它基于database/sql
,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/kmysql
ksqlserver.New(ctx, os.Getenv("DATABASE_URL"), ksql.Config{})
用于SQLServer,它基于database/sql
,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/ksqlserver
ksqlite3.New(ctx, os.Getenv("DATBAASE_PATH"), ksql.Config{})
用于SQLite3,它基于database/sql
和mattn/go-sqlite3,依赖CGO,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/ksqlite3
ksqlite.New(ctx, os.Getenv("DATABASE_PATH"), ksql.Config{})
用于SQLite,它基于database/sql
和modernc.org/sqlite,不需要CGO,通过以下命令下载:
go get github.com/vingarcia/ksql/adapters/modernc-ksqlite
更详细的示例请参见:
./examples/all_adapters/all_adapters.go
当前接口包含用户预期使用的方法,也用于在需要时轻松模拟整个库。
该接口在项目中声明为ksql.Provider
,如下所示。
我们计划保持它非常简单,只有少数经过深思熟虑的函数涵盖所有用例,所以不要期待太多添加:
// Provider描述KSQL的公共行为 // // Insert、Patch、Delete和QueryOne函数在未找到记录或操作期间未更改任何行时返回`ksql.ErrRecordNotFound`。 type Provider interface { Insert(ctx context.Context, table Table, record interface{}) error Patch(ctx context.Context, table Table, record interface{}) error Delete(ctx context.Context, table Table, idOrRecord interface{}) error Query(ctx context.Context, records interface{}, query string, params ...interface{}) error QueryOne(ctx context.Context, record interface{}, query string, params ...interface{}) error QueryChunks(ctx context.Context, parser ChunkParser) error Exec(ctx context.Context, query string, params ...interface{}) (Result, error) Transaction(ctx context.Context, fn func(Provider) error) error }
在下面的示例中,我们将涵盖所有最常见的用例,例如:
更高级的用例在我们的Wiki中有单独的页面说明:
对于更常见的用例,请阅读下面的示例,该示例也可在这里获得,如果你想自己编译。
package main import ( "context" "fmt" "time" "github.com/vingarcia/ksql" "github.com/vingarcia/ksql/adapters/ksqlite3" "github.com/vingarcia/ksql/nullable" ) type User struct { ID int `ksql:"id"` Name string `ksql:"name"` Age int `ksql:"age"` // 以下属性使用了KSQL修饰符, // 你可以在我们的Wiki上找到更多相关信息: // // - https://github.com/VinGarcia/ksql/wiki/Modifiers // // `json`修饰符将地址作为JSON保存在数据库中 Address Address `ksql:"address,json"` // timeNowUTC修饰符将在保存之前将此字段设置为`time.Now().UTC()`: UpdatedAt time.Time `ksql:"updated_at,timeNowUTC"` // timeNowUTC/skipUpdates修饰符将仅在首次创建时将此字段设置为`time.Now().UTC()`, // 并在更新期间忽略它。 CreatedAt time.Time `ksql:"created_at,timeNowUTC/skipUpdates"` } type PartialUpdateUser struct { ID int `ksql:"id"` Name *string `ksql:"name"` Age *int `ksql:"age"` Address *Address `ksql:"address,json"` } type Address struct { State string `json:"state"` City string `json:"city"` } // UsersTable告诉KSQL表名,并且可以使用默认的主键列名:"id" var UsersTable = ksql.NewTable("users") func main() { ctx := context.Background() // 在这个例子中,我们将使用sqlite3: db, err := ksqlite3.New(ctx, "/tmp/hello.sqlite", ksql.Config{ MaxOpenConns: 1, }) if err != nil { panic(err.Error()) } defer db.Close() // 在下面的定义中,请注意BLOB是 // 我们在sqlite中可以用于存储JSON的唯一类型。 _, err = db.Exec(ctx, `CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY, age INTEGER, name TEXT, address BLOB, created_at DATETIME, updated_at DATETIME )`) if err != nil { panic(err.Error()) } var alison = User{ Name: "Alison", Age: 22, Address: Address{ State: "MG", }, } err = db.Insert(ctx, UsersTable, &alison) if err != nil { panic(err.Error()) } fmt.Println("Alison ID:", alison.ID) // 内联插入: err = db.Insert(ctx, UsersTable, &User{ Name: "Cristina", Age: 27, Address: Address{ State: "SP", }, }) if err != nil { panic(err.Error()) } // 删除Alison: err = db.Delete(ctx, UsersTable, alison.ID) if err != nil { panic(err.Error()) } // 检索Cristina,注意如果你省略查询的SELECT部分, // KSQL将根据结构体的字段为你高效地构建它: var cris User err = db.QueryOne(ctx, &cris, "FROM users WHERE name = ? ORDER BY id", "Cristina") if err != nil { panic(err.Error()) } fmt.Printf("Cristina: %#v\n", cris) // 更新Cristina的所有字段: cris.Name = "Cris" err = db.Patch(ctx, UsersTable, cris) // 只更改Cristina的年龄,不触及其他字段: // 部分更新技巧1: err = db.Patch(ctx, UsersTable, struct { ID int `ksql:"id"` Age int `ksql:"age"` }{ID: cris.ID, Age: 28}) if err != nil { panic(err.Error()) } // 部分更新技巧2: err = db.Patch(ctx, UsersTable, PartialUpdateUser{ ID: cris.ID, Age: nullable.Int(28), // (只是一个指向int的指针,如果为null则不会更新) }) if err != nil { panic(err.Error()) } // 列出数据库中的前10个用户 // (每次 运行此示例时都会创建一个新的Cristina) // // 注意:使用此函数时建议设置LIMIT,因为 > 值得注意的是,KSQL 仅在使用 postgres 时缓存预处理语句,因为这是由 `pgx` 执行的,这意味着当使用 MySQL、SQLServer 或 SQLite 时,如果你还计划使用预处理语句,其他库如 `sqlx` 将比 KSQL 快得多。 > 我们正在努力为这些其他数据库添加缓存预处理语句的支持。 ### 基准测试结果 要理解下面的基准测试,你必须知道所有测试都是使用 Postgres 12.1 进行的,并且我们比较了以下工具: - 使用封装 `database/sql` 的适配器的 KSQL - 使用封装 `pgx` 的适配器的 KSQL - `database/sql` - `sqlx` - `pgx` (使用 `pgxpool`) - `gorm` - `sqlc` - `sqlboiler` 对于每个工具,我们运行 3 种不同的查询: `insert-one` 查询如下: `INSERT INTO users (name, age) VALUES ($1, $2) RETURNING id` `single-row` 查询如下: `SELECT id, name, age FROM users OFFSET $1 LIMIT 1` `multiple-rows` 查询如下: `SELECT id, name, age FROM users OFFSET $1 LIMIT 10` 请记住,一些测试的工具(如 GORM)实际上在内部构建查询,因此用于基准测试的实际代码可能与上面的示例略有不同。 不多说了,以下是结果: ```bash $ make bench TIME=5s sqlc generate go test -bench=. -benchtime=5s goos: linux goarch: amd64 pkg: github.com/vingarcia/ksql/benchmarks cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz BenchmarkInsert/ksql/sql-adapter/insert-one-12 9711 618727 ns/op BenchmarkInsert/ksql/pgx-adapter/insert-one-12 10000 555967 ns/op BenchmarkInsert/sql/insert-one-12 9450 624334 ns/op BenchmarkInsert/sql/prep-stmt/insert-one-12 10000 555119 ns/op BenchmarkInsert/sqlx/insert-one-12 9552 632986 ns/op BenchmarkInsert/sqlx/prep-stmt/insert-one-12 10000 560244 ns/op BenchmarkInsert/pgxpool/insert-one-12 10000 553535 ns/op BenchmarkInsert/gorm/insert-one-12 9231 668423 ns/op BenchmarkInsert/sqlc/insert-one-12 9589 632277 ns/op BenchmarkInsert/sqlc/prep-stmt/insert-one-12 10803 560301 ns/op BenchmarkInsert/sqlboiler/insert-one-12 9790 631464 ns/op BenchmarkQuery/ksql/sql-adapter/single-row-12 44436 131191 ns/op BenchmarkQuery/ksql/sql-adapter/multiple-rows-12 42087 143795 ns/op BenchmarkQuery/ksql/pgx-adapter/single-row-12 86192 65447 ns/op BenchmarkQuery/ksql/pgx-adapter/multiple-rows-12 74106 79004 ns/op BenchmarkQuery/sql/single-row-12 44719 134491 ns/op BenchmarkQuery/sql/multiple-rows-12 43218 138309 ns/op BenchmarkQuery/sql/prep-stmt/single-row-12 89328 64162 ns/op BenchmarkQuery/sql/prep-stmt/multiple-rows-12 84282 71454 ns/op BenchmarkQuery/sqlx/single-row-12 44118 132928 ns/op BenchmarkQuery/sqlx/multiple-rows-12 43824 137235 ns/op BenchmarkQuery/sqlx/prep-stmt/single-row-12 87570 66610 ns/op BenchmarkQuery/sqlx/prep-stmt/multiple-rows-12 82202 72660 ns/op BenchmarkQuery/pgxpool/single-row-12 94034 63373 ns/op BenchmarkQuery/pgxpool/multiple-rows-12 86275 70275 ns/op BenchmarkQuery/gorm/single-row-12 83052 71539 ns/op BenchmarkQuery/gorm/multiple-rows-12 62636 89652 ns/op BenchmarkQuery/sqlc/single-row-12 44329 132659 ns/op BenchmarkQuery/sqlc/multiple-rows-12 44440 139026 ns/op BenchmarkQuery/sqlc/prep-stmt/single-row-12 91486 66679 ns/op BenchmarkQuery/sqlc/prep-stmt/multiple-rows-12 78583 72583 ns/op BenchmarkQuery/sqlboiler/single-row-12 70030 87089 ns/op BenchmarkQuery/sqlboiler/multiple-rows-12 69961 84376 ns/op PASS ok github.com/vingarcia/ksql/benchmarks 221.596s 基准测试执行时间: 2023-10-22 基准测试执行的提交: 35b6882317e82de7773fb3908332e8ac3d127010
测试使用 docker-test
来设置所有支持的数据库,这意味着:
你需要安装 docker
你必须能够不使用 sudo
就运行 docker,即
如果你不是 root 用户,你应该将自己添加到 docker 组,例如:
$ sudo usermod <your_username> -aG docker
然后重新启动你的登录会话(或者直接重启)
最后,只需运行一次 make pre-download-all-images
,这样你的测试就不会
因下载数据库镜像而超时。
之后,你可以通过以下方式运行测试:
make test
Upsert
辅助方法ksqltest.FillStructWith
以处理带有 ksql:"..,json"
标记的属性kbuilder
包ksql.NewTable()
中预加载所有方言的插入方法Update
、Insert
和 Delete
使用预处理语句。.Transaction(db ksql.Provider)
更改为 .Transaction(ctx context.Context)
.Query()
方法返回 type Query interface { One(); All(); Chunks(); }
Update()
方法,不像 Patch()
那样忽略 NULL 值进行更新
skipNullUpdates
,使 Update 函数执行 Patch
的工作Patch
函数NewTable()
重命名为 Table()
,这样在方便时可以内联声明AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
一站式AI创作平台
提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作
AI办公助手,复杂任务高效处理
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号