仓颉版的mysql客户端
介绍
基于CDBC标准封装的MySQL C语言libmysqlclient库
特性
- 数据库连接管理
- 数据表创建与删除
- 数据库增删改查操作
支持平台
| 操作系统 | 是否支持 |
|---|---|
| Windows | 是 |
| Linux-arrch64 | 是 |
| Linux-x86 | 是 |
软件架构
源码目录
.
├─ .gitee
│ └─ PULL_REQUEST_TEMPLATE.zh-CN.md
├─ .gitignore
├─ CHANGELOG.md
├─ gitee_gate.cfg
├─ module.json
├─ LICENSE
├─ README.md
├─ README.OpenSource
├─ doc
│ ├─ assets
│ └─ feature_api.md
├─ libmysqlclient_c
├─ src
│ └─ mysqlclient
└─ test
├─ DOC
├─ FUZZ
├─ Reliability
├─ HLT
└─ LLT
doc文档目录,存放API接口等文档资料libmysqlclient_c需自行编译的C语言文件src源代码目录test测试用例目录test DOC功能演示示例test FUZZ模糊测试用例test Reliability高并发测试场景test HLT高阶逻辑测试用例test LLT底层逻辑测试用例
接口规范
核心类与成员函数说明详见 API文档
操作指南
编译流程
静态库编译方法参见:静态库编译指南
- 本项目基于mysqlclient8.0.33开发,需预先安装mysqlclient依赖包,下载地址:
https://downloads.mysql.com/archives/community/
Windows系统需配置msys2与mingw64环境:
- msys2安装包:
https://github.com/msys2/msys2-installer/releases/download/2023-03-18/msys2-x86_64-20230318.exe - mingw64压缩包:
https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-posix-seh-msvcrt-rt_v10-rev2.7z
将mingw64解压至msys2根目录后:
进入mingw64的bin目录,复制mingw32-make.exe到当前目录并重命名为make.exe
- 克隆mysqlclient-ffi项目代码库
git clone https://gitcode.com/Cangjie-TPC/mysqlclient-ffi.git
3、切换目录
cd mysqlclient-ffi
4、在当前目录下新建一个名为 lib 的文件夹
5、迁移库文件
在 Linux 环境下,将 libmysqlclient.so、libmysqlclient.so.21 和 libmysqlclient.so.21.2.33 这三个动态链接库文件复制到 lib 目录中,最终目录结构如下所示
├─ lib
│ ├─ libmysqlclient.so
│ ├─ libmysqlclient.so.21
│ └─ libmysqlclient.so.21.2.33
文件 libmysqlclient.so、libmysqlclient.so.21 和 libmysqlclient.so.21.2.33 通常位于 /usr/lib/mysql/ 目录或 /usr/lib/x86_64-linux-gnu/ 目录下。
若未找到,可执行以下指令后再到对应目录中查找 so 包:
sudo apt-get install libmysqlclient-dev
在 Windows 环境下,将 libmysql.dll 复制到 lib 目录中,目录结构如下
├─ lib
│ └─ libmysql.dll
libmysql.dll 通常位于MySQL安装目录下的lib文件夹中
6、编译mysqlclient_cj及项目
在linux-x86环境下执行build_linux.sh脚本,在linux-arrch64环境下运行build_aarch64.sh脚本
最终生成的目录结构如下
├─ lib
│ ├─ libmysqlclient_cj.so
│ ├─ libmysqlclient.so
│ ├─ libmysqlclient.so.21
│ └─ libmysqlclient.so.21.2.33
在 Windows 环境下运行 build_win.bat 文件。需注意修改 build_win.bat 中的 msys2 路径。
最终生成的目录结构如下
├─ lib
│ ├─ libmysql.dll
│ └─ libmysqlclient_cj.dll
7、编译示例文件
示例文件位于 test/DOC/mysql_examples.cj
将${path}替换为用户项目的实际本地路径
Linux 编译命令
cd target/release/mysqlclient_ffi
cjc --import-path ${path}/mysqlclient-ffi/target/release -L ${path}/mysqlclient-ffi/target/release/mysqlclient_ffi -l mysqlclient -l mysqlclient_cj -l mysqlclient_ffi${path}/mysqlclient-ffi/test/DOC/mysql_examples.cj -O0 -Woff all
Windows 编译指南
cd target/release/mysqlclient_ffi
cjc --import-path ${path}/mysqlclient-ffi/target/release -L ${path}/mysqlclient-ffi/target/release/mysqlclient_ffi -l mysql -l mysqlclient_cj -l mysqlclient_ffi${path}/mysqlclient-ffi/test/DOC/mysql_examples.cj -O0 -Woff all
8、运行执行文件
Linux 运行
./main
Windows 运行
./main.exe
功能演示
// EXEC: cjc %import-path %L %l %f
// EXEC: ./main
import mysqlclient_ffi.*
import std.database.sql.*
import std.time.*
main(): Int64 {
// 初始化数据库驱动
let mysqlDriver: MysqlDriver = MysqlDriver("mysql")
if (mysqlDriver.name == "mysql") {
println("pass1")
}
if (mysqlDriver.version.size > 0) {
println("pass2")
}
let arr: Array<(String, String)> = Array<(String, String)>()
// 通过connectionString和选项打开数据源
let mysqlDatasource: MysqlDatasource = mysqlDriver.open(
"HOST=127.0.0.1;USER=root;PASSWD=123;DB=mysql;PORT=3306;UNIX_SOCKET=;CLIENT_FLAG=0",
arr
)
// 返回一个可用的链接
let mysqlConnection: MysqlConnection = mysqlDatasource.connect()
// 删除t_test名称数据表
var mysqlStatement: MysqlStatement = mysqlConnection.prepareStatement("drop table if exists t_test")
mysqlStatement.update()
mysqlStatement.close()
// 创建t_test名称数据表
mysqlStatement = mysqlConnection.prepareStatement("create table t_test(id bigint, name varchar(50))")
mysqlStatement.update()
mysqlStatement.close()
// 插入数据预执行语句
mysqlStatement = mysqlConnection.prepareStatement("insert into t_test(id,name) VALUES(?,?)")
if (mysqlStatement.parameterCount == 2) {
println("pass3")
}
// 执行插入语句插入数据
mysqlStatement.set<Int64>(0, 1)
mysqlStatement.set<String>(1, "lihao111")
var mysqlUpdateResult: MysqlUpdateResult = mysqlStatement.update()
if (mysqlUpdateResult.rowCount == 1) {
println("pass4")
}
// 执行插入语句插入数据
mysqlStatement.set<Int64>(0, 2)
mysqlStatement.set<String>(1, "lihao222")
mysqlUpdateResult = mysqlStatement.update()
if (mysqlUpdateResult.rowCount == 1) {
println("pass5")
}
mysqlStatement.close()
// 查询语句预执行语句
mysqlStatement = mysqlConnection.prepareStatement("select * from t_test where id = ?")
if (mysqlStatement.parameterCount == 1) {
println("pass6")
}
// 执行查询语句
mysqlStatement.set<Int64>(0, 2)
var mysqlQueryResult: MysqlQueryResult = mysqlStatement.query()
let mysqlColumnInfos: Array<MysqlColumnInfo> = mysqlQueryResult.mysqlColumnInfos
if (mysqlColumnInfos.size == 2) {
println("pass7")
}
if (mysqlColumnInfos[0].name == "id") {
println("pass8")
}
if (mysqlColumnInfos[0].typeName == "SqlInt64") {
println("pass9")
}
if (mysqlColumnInfos[0].displaySize == 0) {
println("pass10")
}
if (mysqlColumnInfos[0].length == 20) {
println("pass11")
}
if (mysqlColumnInfos[0].scale == 0) {
println("pass12")
}
if (!mysqlColumnInfos[0].nullable) {
println("pass13")
}
if (mysqlColumnInfos[1].name == "name") {
println("pass14")
}
if (mysqlColumnInfos[1].typeName == "SqlString") {
println("pass15")
}
if (mysqlColumnInfos[1].displaySize == 0) {
println("pass16")
}
if (mysqlColumnInfos[1].length == 200) {
println("pass17")
}
if (mysqlColumnInfos[1].scale == 0) {
println("pass18")
}
if (!mysqlColumnInfos[1].nullable) {
println("pass19")
}
// 获取数据
var isBool: Bool = mysqlQueryResult.next()
if (isBool) {
println("pass20")
}
if (mysqlQueryResult.get<Int64>(0) == 2) {
println("pass21")
}
if (mysqlQueryResult.get<String>(1) == "lihao222") {
println("pass22")
}
mysqlStatement.close()
// 删除语句预执行语句
mysqlStatement = mysqlConnection.prepareStatement("delete from t_test where name = ?")
if (mysqlStatement.parameterCount == 1) {
println("pass23")
}
// 执行删除语句
mysqlStatement.set<String>(0, "lihao222")
mysqlUpdateResult = mysqlStatement.update()
if (mysqlUpdateResult.rowCount == 1) {
println("pass24")
}
mysqlStatement.close()
// 查询语句预执行语句
mysqlStatement = mysqlConnection.prepareStatement("select * from t_test where id = ?")
if (mysqlStatement.parameterCount == 1) {
println("pass25")
}
// 执行查询语句
mysqlStatement.set<Int64>(0, 2)
mysqlQueryResult = mysqlStatement.query()
// 获取数据
isBool = mysqlQueryResult.next()
if (!isBool) {
println("pass26")
}
mysqlStatement.close()
// 更新语句预执行语句
mysqlStatement = mysqlConnection.prepareStatement("update t_test set name = ? where id = ?")
if (mysqlStatement.parameterCount == 2) {
println("pass27")
}
// 执行更新语句
mysqlStatement.set<Int64>(1, 1)
mysqlStatement.set<String>(0, "lihao333")
mysqlUpdateResult = mysqlStatement.update()
if (mysqlUpdateResult.rowCount == 1) {
println("pass28")
}
mysqlStatement.close()
// 查询语句预执行语句
mysqlStatement = mysqlConnection.prepareStatement("select * from t_test where id = ?")
if (mysqlStatement.parameterCount == 1) {
println("pass29")
}
// 执行查询语句
mysqlStatement.set<Int64>(0, 1)
mysqlQueryResult = mysqlStatement.query()
if (mysqlColumnInfos.size == 2) {
println("pass30")
}
// 获取数据
isBool = mysqlQueryResult.next()
if (isBool) {
println("pass31")
}
if (mysqlQueryResult.get<Int64>(0) == 1) {
println("pass32")
}
if (mysqlQueryResult.get<String>(1) == "lihao333") {
println("pass33")
}
mysqlStatement.close()
// 删除t_test名称数据表
mysqlStatement = mysqlConnection.prepareStatement("drop table if exists t_test")
mysqlStatement.update()
mysqlStatement.close()
// 关闭链接
mysqlConnection.close()
return 0
}
执行结果如下:
pass1
pass2
pass3
pass4
pass5
pass6
pass7
pass8
pass9
pass10
pass11
pass12
pass13
pass14
pass15
pass16
pass17
pass18
pass19
pass20
pass21
pass22
pass23
pass24
pass25
pass26
pass27
pass28
pass29
pass30
pass31
pass32
pass33
约束与限制
本项目基于 mysqlclient8.0.33 开发
开源协议
本项目采用 GPLv2 协议,您可以自由地使用并参与开源协作。
参与贡献
我们诚挚欢迎您通过提交PR、创建Issue或其他任何形式参与项目贡献。