
数据库关系型数据库【免费下载链接】mariadb-driverMariaDB驱动适配MySQL、TiDB、OceanBase数据库。项目地址https://gitcode.com/Cangjie-SIG/mariadb-driver点击查看免费下载mariadb-driver 是使用仓颉Cangjie语言编写的 MariaDB 原生数据库驱动基于 MySQL 客户端/服务器协议实现可适配 MySQL、TiDB、OceanBase 等兼容数据库。本指南以仓库根目录 readme.md 为核心脉络完整讲解从依赖引入、编译构建到连接数据源、查询/更新/事务操作以及全部连接参数的实战用法并深入对应源码说明底层实现原理。读完本文你将能够在自己的 Cangjie 项目中独立完成驱动集成、编写可运行的 CRUD 与事务代码并针对生产环境正确配置 SSL 与连接池参数。1 项目概览与核心特性mariadb-driver 由社区开发者 Yesokim 实现并维护是一个原生不使用任何第三方数据库中间件的 MariaDB 驱动程序。官方文档明确其定位适配 MySQL、TIDB、OceanBase 等数据库。这意味着同一套驱动 API 可以用于连接这几类遵循 MySQL 协议的服务端例如仓库测试用例 driver_test.cj 中就分别针对 mariadb、mysql、tidb、oceanbase 四类数据库执行了相同的连接与读写逻辑。项目核心特性包括纯 Cangjie 实现整个协议栈与数据库访问层均由仓颉语言编写位于仓库 src 目录遵循仓颉标准数据库接口驱动面向std.database.sql标准库接口开发方便与仓颉生态中的上层组件集成README 中标注了配套的 ORM 框架CORM内置连接池驱动声明preferredPooling为 true见 driver.cj打开数据源即返回PooledDatasource并提供完整的池化参数控制支持服务端/客户端两种预编译模式以及 SSL/TLS 传输层加密详见第 6、7 章。版本信息方面README 徽标标注 release v1.0.0、cjc v1.0.0而当前 cjpm.toml 中包版本为 2.0.2、cjc-version为 1.1.0changelog.md 记录有 v2.0.0 版本条目读者应以实际拉取的仓库版本为准。2 架构项目结构与分层设计2.1 项目结构README 给出的顶层结构如下对照当前仓库实际内容src/result、src/test、src/xa为文档规划目录当前源码按cdbc/connection/protocol三包组织├── doc └── readme-image └── src ├── cdbc ├── connection ├── protocol ├── result ├── test └── xa ├── CHANGELOG ├── cjpm.lock ├── cjpm.toml ├── LICENSE ├── README.md结合源码可以梳理出清晰的三层职责划分目录职责关键文件src/cdbc面向使用者的数据库访问层实现std.database.sql标准接口Driver、Datasource、Connection、Statement、QueryResult 等driver.cj、connection.cj、prepare_statement_server.cjsrc/connection连接内部实现与协议交互TCP 建连、认证、SSL、事务、结果集封装maria_connection_factory.cj、maria_connection.cj、maria_transaction.cjsrc/protocolMySQL 协议编解码握手、能力标志、列类型、各命令报文server_handshake.cj、capability.cj、column_type.cj2.2 接口说明与驱动注册README 指出接口设计参考仓颉官方的数据库接口文档。在实际实现中驱动的入口非常简洁文件 driver.cj 在包加载时即执行let _ DriverManager.register(mariadb, MariaDBDriver())将驱动实例以mariadb为名注册进DriverManager因此后续代码可以统一通过DriverManager.getDriver(mariadb)获取驱动对象这与标准库的数据库接口设计保持一致。3 环境准备OpenSSL 3 与 CANGJIE_STDX_PATH在使用该驱动之前需要确认两个环境前提OpenSSL 3 动态库README 明确指出仓颉提供的摘要算法和加密算法依赖 OpenSSL3 的 crypto 动态库文件因此使用该驱动时需要确保本地环境有相应的动态库文件Windows 下可通过安装 OpenSSL 预编译包获得对应 DLL。stdx 路径环境变量cjpm.toml中通过bin-dependencies引用 stdx需要额外设置环境变量CANGJIE_STDX_PATH值为 stdx 的路径。README 中给出的示例输出为$ echo $CANGJIE_STDX_PATH C:\Users\30247\Desktop\Cangjie\Cangjie-1.0.0\cangjie-stdx-windows-x64-1.0.0.1\windows_x86_64_llvm\static\stdx从 cjpm.toml 可以看到驱动为以下目标平台都声明了path-option [${CANGJIE_STDX_PATH}]x86_64-w64-mingw32Windows x64x86_64-unknown-linux-gnuLinux x64x86_64-apple-darwin与aarch64-apple-darwinmacOSaarch64-unknown-linux-gnuLinux ARM644 编译构建在项目中引入 mariadb-driver在项目的cjpm.toml的[dependencies]中增加以下配置然后执行cjpm update即可将驱动引入项目README 原文示例[dependencies] mariadb {git https://gitcode.com/Cangjie-SIG/mariadb-driver.git, branchmaster}引入后在代码中通过如下 import 使用驱动提供的能力import std.database.sql.* import mariadb.cdbc.*mariadb.cdbc包导出了驱动、数据源、连接、语句、结果集等全部面向使用者的类型底层mariadb.connection、mariadb.protocol属于 protected 内部包无需也不应直接引用。5 快速上手功能示例5.1 准备测试表README 提供了名为simple的示例表覆盖了整型、字符串、浮点、精确小数、日期时间等常用类型CREATE TABLE simple ( id int NOT NULL AUTO_INCREMENT, varchar_col varchar(255) DEFAULT NULL, int_col int DEFAULT NULL, double_col double(10,4) DEFAULT NULL, decimal_col decimal(10,5) DEFAULT NULL, date_col date DEFAULT NULL, time_col time DEFAULT NULL, datetime_col datetime DEFAULT NULL, PRIMARY KEY (id) )仓库 doc/test.sql 中还提供了一套更全面的测试建表脚本包含数字类型表numeric_typesbool/bit/tinyint/smallint/mediumint/int/bigint/float/double/decimal 及其无符号变体、时间类型表time_typesdate/time/datetime/timestamp/year以及字符类型表character_typeschar/varchar/tinytext/text/mediumtext/longtext/blob/json/set/enum同时包含三种认证插件测试用户mysql_native_password、sha256_password、caching_sha2_password的创建语句适合作为驱动功能验证的基准环境。5.2 连接数据源三个功能示例的公共步骤都是通过DriverManager取驱动 →open打开数据源 →connect获取连接。以 README 的查询示例为例import std.time.* import std.math.numeric.* import std.database.sql.* import mariadb.cdbc.* main(): Unit { var driver DriverManager.getDriver(mariadb).getOrThrow() var property1 (username, test_user) var property2 (password, test_user) var property3 (database, driver_test) var dataSource driver.open(mariadb://localhost, [property1, property2, property3]) var connection dataSource.connect() ... }这里值得说明open(url, opts)的语义因为其 URL 解析逻辑直接决定了可用的连接写法。查看 driver.cj 的实现URL 的 scheme 必须为mariadb否则抛出IllegalArgumentException(Bad connection url)URL 中的host、port、路径部分自动去除前导/作为 database、query字符串以分割的keyvalue以及userInfouser:passhost形式都会被解析为数据源参数传入的opts属性数组如(username, test_user)会逐项覆盖/补充参数其中以pool.开头的池化参数还会同步设置到PooledDatasource上。因此以下两种写法等价// 写法一URL 携带路径与查询串 driver.open(mariadb://localhost:3306/driver_test?ssl.modedisabled, []) // 写法二属性数组携带参数README 示例风格 driver.open(mariadb://localhost:3306, [(username,test_user), (password,test_user), (database,driver_test)])注意driver.open返回的是PooledDatasource测试用例 driver_test.cj 中通过dataSource as PooledDatasource断言了这一行为说明驱动默认启用了连接池。5.3 查询数据QueryREADME 的完整查询示例import std.time.* import std.math.numeric.* import std.database.sql.* import mariadb.cdbc.* main(): Unit { var driver DriverManager.getDriver(mariadb).getOrThrow() var property1 (username, test_user) var property2 (password, test_user) var property3 (database, driver_test) var dataSource driver.open(mariadb://localhost, [property1, property2, property3]) var connection dataSource.connect() var statemnt connection.prepareStatement(select * from simple) var result statemnt.query() while (result.next()) { result.getUInt64(1) | println result.getOrNullString(2) | println result.getOrNullInt32(3) | println result.getOrNullFloat64(4) | println result.getOrNullDecimal(5) | println result.getOrNullDateTime(6) | println result.getOrNullDateTime(7) | println result.getOrNullDateTime(8) | println } }要点解析prepareStatement生成预编译语句对象query()返回QueryResult通过next()逐行迭代取值 API 有两个getT(index)在值为 NULL 时抛出NoneValueExceptiongetOrNullT(index)返回可空类型见 query_result.cj。对于可能为 NULL 的列示例中varchar_col、int_col等均允许 NULL应使用getOrNull列索引从 1 开始源码中对index 0会抛出IllegalArgumentException。getT的类型参数并非任意指定而是由驱动内部的结果集读取方法支撑。协议层 column_type.cj 定义了列类型到仓颉类型的映射常用映射如下MySQL/MariaDB 列类型仓颉读取类型有符号仓颉读取类型UNSIGNEDTINYINTInt8UInt8SMALLINTInt16UInt16MEDIUMINT / INTInt32UInt32BIGINTInt64UInt64FLOATFloat32—DOUBLEFloat64—DECIMALDecimal—DATE / TIME / DATETIME / TIMESTAMPDateTime—YEARInt32—BITArrayByte—JSONString—ENUM / SETString—BLOB 系列ArrayByte—VARCHAR / CHAR / TEXT 系列String—QueryResult还提供columnInfos属性获取列元数据。另外注意一个使用约束底层 maria_connection.cj 的checkInexpectantOkResponse会拦截“用 query 方法执行非 SELECT 语句”的用法并抛出异常即 DDL/DML 必须走 update 路径。5.4 更新数据Insert、Update、DeleteREADME 的完整更新示例import std.database.sql.* import mariadb.cdbc.* import std.time.DateTime import std.math.numeric.Decimal main(): Unit { var driver DriverManager.getDriver(mariadb).getOrThrow() var property1 (username, test_user) var property2 (password, test_user) var property3 (database, driver_test) var dataSource driver.open(mariadb://localhost, [property1, property2, property3]) var connection dataSource.connect() var statemnt connection.prepareStatement(insert into simple values (?, ?, ?, ?, ?, ?, ?, ?)) statemnt.set(1, 1000) statemnt.set(2, mariadb) statemnt.setNull(3) statemnt.set(4, 123.456789) statemnt.set(5, Decimal.parse(1.234567)) statemnt.set(6, DateTime.now()) statemnt.set(7, DateTime.now()) statemnt.set(8, DateTime.now()) var result statemnt.update() println(effect row: ${result.rowCount} lastInsertId: ${result.lastInsertId}) }要点解析占位符从 1 开始编号setT(index, value)支持Bool、Int8/16/32/64、UInt8/16/32/64、Float16/32/64、Rune、String、DateTime、BigInt、Decimal、ArrayByte、InputStream等类型的可空包装值见 prepare_statement_server.cjInputStream会走长数据Long Data通道传输setNull(index)显式写入 NULL等价于set(index, OptionAny.None)update()返回UpdateResult其rowCount属性为影响行数、lastInsertId属性为自增主键回填值见 update_result.cj。对于 INSERTlastInsertId会在服务端返回的自增 id 基础上按语句中的插入行数修正见 prepare_statement_server.cj。5.5 事务操作README 的完整事务示例import mariadb.cdbc.* import std.database.sql.* main(){ var driver DriverManager.getDriver(mariadb).getOrThrow() var property1 (username root) var property2 (password, password) var property3 (database, test) var dataSource driver.open(mariadb://localhost:3306, [property1,property2,property3]) var connection dataSource.connect() var transaction connection.createTransaction() transaction.begin() transaction.commit() }事务对象通过connection.createTransaction()获取。从 transaction.cj 的实现可以看到驱动提供的能力远不止 begin/commit还包括隔离级别isoLevel属性可读可写支持ReadUncommitted、ReadCommitted、RepeatableRead默认与 MySQL 默认一致、Serializable初始化时会通过SELECT transaction_isolation读取当前会话实际级别访问模式accessMode属性支持ReadOnly/ReadWrite切换初始化时读取SELECT transaction_read_only回滚与保存点rollback()、save(savePointName)、rollback(savePointName)、release(savePointName)对应 SAVEPOINT / ROLLBACK TO / RELEASE SAVEPOINT 语句deferrableMode当前实现为抛出UnsupportedException()的占位见 transaction.cj。这些操作最终由 maria_transaction.cj 翻译为具体的 SQL 命令BEGIN、COMMIT、ROLLBACK、SET SESSION autocommit 0/1、SET SESSION transaction_isolation ...等经连接通道发送给服务端执行。6 连接参数详解README 第 3.3 节给出了完整的连接参数表下面完整继承并依据 params.cj 对键名与默认值进行核对、补充。表中键名以源码常量定义为准README 表格中connection_timeout一项实际键名为connection.timeout与其余点分式键名保持一致。选项名功能可选值默认值Requireusername数据库用户名Yespassword数据库密码Yeshost主机地址Yesport服务端口3306Nodatabase数据库Noconnection.timeoutconnect 操作的超时时间单位 ms。Noprepare.mode预编译模式server 或 clientserverNossl.mode传输层加密模式disabled、preferred默认、required、verify_ca、verify_fullpreferredNossl.ca证书颁发机构CA证书文件的路径名Nossl.cert客户端 SSL 公钥证书文件的路径名Nossl.key客户端 SSL 私钥文件的路径名使用了 ssl.cert 必须指定 ssl.key 参数ssl.key.password客户端 SSL 私钥文件的密码Nossl.sni客户端通过该标识在握手过程开始时试图连接到哪个主机名Notls1.2.ciphersuites客户端允许 TLSv1.2 及以下加密连接使用的密码套件Notls1.3.ciphersuites客户端允许 TLSv1.3 加密连接使用的密码套件Notls.version支持的 TLS 版本号逗号分隔字符串如TLSv1.2,TLSv1.3Nopool.connection.timeout从池中获取连接的超时时间单位 s30Nopool.idle.timeout连接在池中允许闲置的最长时间超过会被回收单位 m10Nopool.keepalive.time检查空闲连接健康状况的间隔时间防止被数据库或网络基础设施超时单位 m1Nopool.max.idle.size最大空闲连接数超过会被关闭负数或 0 表示无限制0Nopool.max.life.time自连接创建以来的持续时间之后连接自动关闭单位 m30Nopool.max.size连接池最大连接数负数或 0 表示无限制10No6.1 基础连接参数username、password、host在认证流程中为必需项源码 maria_connection_factory.cj 在构造握手响应时若缺少 username 或 password 会分别抛出IllegalArgumentException(Required connection parameters: username/password)。从实现看host与port实际带有缺省值——建连函数connectToServer中host缺省为localhost、port缺省为3306见 maria_connection_factory.cjREADME 将 host 标为必填可视为显式声明连接地址的推荐做法。connection.timeout未设置时使用套接字默认连接行为设置后按毫秒换算为Duration传入socket.connect(timeout: ...)。6.2 SSL/TLS 参数ssl.mode五个取值控制传输层加密策略disabled完全不加密preferred默认在服务端支持 SSL 时启用、否则回退明文required强制加密若服务端不支持则建连失败源码中对不支持 SSL 且模式非 disabled/preferred 的情况抛出ConnectFailedException见 maria_connection_factory.cjverify_ca、verify_full进一步要求证书校验。ssl.cert与ssl.key配套提供客户端证书与私钥路径私钥可按 RSA/ECDSA 算法从 PEM 文件解析ssl.key.password用于加密私钥ssl.sni指定握手时客户端宣称的主机名tls1.2.ciphersuites与tls1.3.ciphersuites分别限定两个 TLS 版本的密码套件源码常量注释给出了冒号分隔示例如TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_DHE_RSA_WITH_AES_128_CBC_SHA与TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256。6.3 连接池参数以pool.开头的参数由 driver.cj 中的setPooledDataSourceParam解析并直接映射到PooledDatasource的对应属性单位换算关系如下参数PooledDatasource 属性单位换算pool.connection.timeoutconnectionTimeout秒 × Duration.secondpool.idle.timeoutidleTimeout分 × Duration.minutepool.keepalive.timekeepaliveTime分 × Duration.minutepool.max.idle.sizemaxIdleSize直接整数赋值pool.max.life.timemaxLifeTime分 × Duration.minutepool.max.sizemaxSize直接整数赋值各参数解析失败时抛出IllegalArgumentException提示语中带出具体参数名如Parse PoolMaxSize failed: ...便于排查。测试用例 driver_test.cj 演示了同时配置全部六个池化参数的写法并逐一打印池对象属性加以验证可视为参数合法取值范围与单位换算的参考样例。7 预编译模式与结果集实现源码级补充prepare.mode决定prepareStatement返回的语句对象类型。查看 connection.cj未配置时默认返回ServerPrepareStatement配置server返回服务端预编译client返回客户端预编译其他值抛出异常。server 模式默认调用链为sendPrepareCOM_STMT_PREPARE→ 服务端返回语句 id 与参数/列元数据 → 执行时走executeQueryPrepare/executeUpdatePrepareCOM_STMT_EXECUTE。服务端预编译还支持游标在语句上设置fetchSize选项后prepare_statement_server.cj 会调用executeQueryPrepareWithCursor返回CursorResultSet通过FetchCommand分批拉取结果见 maria_connection.cj适合大结果集场景。该模式下可通过parameterColumnInfos属性获取服务端返回的参数列信息。client 模式ClientPrepareStatement在本地按?拆分 SQL 并逐个拼接参数值见 prepare_statement_client.cjSQL 构建结果会被缓存以复用该模式不向服务端发送预编译命令parameterColumnInfos会抛出UnsupportedException提示“需要设置 prepare.modeserver”。结果集实现普通文本查询返回TextResultSet文本协议逐包解析服务端预编译查询返回BinaryResultSet二进制协议游标场景返回CursorResultSet三者都实现统一的内部ResultSet接口向使用者暴露一致的读取方法见 result_set.cj。8 认证与 SSL 握手流程源码级补充驱动在建立连接时遵循 MySQL 协议握手流程maria_connection_factory.cj 的createAuthedConnection完整实现了这一过程建立 TCP 连接可带connection.timeout初始化MariaConnection并读取服务端握手包解析握手包中的能力标志与认证插件Handshake类校验协议版本必须为 10解析服务器版本、线程 id、随机盐salt、能力标志、字符集、认证插件名见 server_handshake.cj依据ssl.mode决定是否升级为 TLS 连接若启用 SSL先发送 SSL 请求再执行 TLS 握手成功后将连接套接字替换为TlsSocket按握手包声明的认证插件计算加密密码并发送认证响应支持三种主流插件mysql_native_passwordSHA1 摘要加密sha256_passwordSSL 通道下明文传输否则请求服务端公钥做 RSA 加密performFullAuthenticationcaching_sha2_password支持快速认证FastAuthSuccess与完整认证PerformFullAuthentication两种状态机完整认证在非 SSL 通道下同样采用公钥加密根据服务端响应Ok/Error/PublicKey/AuthSwitch/AuthStatus完成后续交互任一步骤失败均抛出ConnectFailedException。客户端默认能力标志在 capability.cj 中集中设置含Protocol41、ConnectWithDB、SSL、Transactions、MultiStatements、PluginAuth、DeprecateEOF等其中 SSL 能力在 TLS 场景动态开启。9 目前已知的一些问题README 中“目前已知的一些问题”章节目前为空白尚未公开列出已知缺陷。作为补充从当前源码结构可以观察到以下几处值得使用者注意的实现现状均为源码事实非文档承诺tls.version参数虽在 README 参数表中列出但源码 params.cj 中该常量处于注释状态maria_connection_factory.cj 中对应的 TLS 版本设置逻辑同样被注释因此该参数当前未生效TLS 版本由TlsClientConfig默认策略决定maria_connection.cj 的countSqlStatements通过按;分割统计 SQL 条数源码注释表明该算法后续将替换为更安全的实现多语句更新场景的行为需以实测为准params.cj 中prepare.mode的注释标注“默认值为 client”与 README 及 connection.cj 中默认走 server 模式的实际实现不一致使用时以“未配置时默认 server 模式”为准。10 参与贡献本项目由 Yesokim 实现并维护技术支持和意见反馈通过 Issue 提交。项目基于 Apache License 2.0 开源欢迎提交 PR欢迎参与任何形式的贡献。仓库根目录的 license 文件即为许可证全文。小结本文以仓库 readme.md 为骨架完整覆盖了 mariadb-driver 的特性定位、分层架构、环境依赖、依赖引入、三大功能示例Query / Update / 事务、全部连接参数含连接池与 SSL并延伸至认证流程、预编译模式、结果集与类型映射等源码实现。整体脉络可以概括为DriverManager取驱动 →open解析 URL 与属性并构建池化数据源 →connect完成 TCP/SSL/认证握手 →prepareStatement按prepare.mode生成预编译语句 →query/update/transaction完成数据操作。按上述步骤即可在生产项目中稳定接入 MariaDB、MySQL、TiDB、OceanBase 等数据库。赞分享数据库关系型数据库【免费下载链接】mariadb-driverMariaDB驱动适配MySQL、TiDB、OceanBase数据库。项目地址https://gitcode.com/Cangjie-SIG/mariadb-driver点击查看免费下载相关推荐把第三方硬盘装进群晖白名单从下载到生效的完整实操把第三方硬盘装进群晖白名单从下载到生效的完整实操 刚把新买的硬盘塞进群晖NAS存储管理器就给它标了个「不受支持」别慌盘没问题是它不在群晖官方的兼容名单运维存储CLIorchestrator 项目实战Go-MySQL-Drivergo-sql-driver/mysqlDSN 配置与连接池调优完全指南orchestrator 项目实战Go MySQL Drivergo sql driver/mysqlDSN 配置与连接池调优完全指南 本文以 orche后端数据库Gel Python 客户端完整指南连接池、查询 API、事务与配置gel.create_async_client 实战Gel Python 客户端完整指南连接池、查询 API、事务与配置gel.create_async_client 实战 本文是 Gel 官方 Pytho数据库图数据库关系型数据库上一篇ccg-workflow 前端设计降噪指南用 quieter 技能将过度刺激的界面打磨为精致优雅下一篇免费开源STL到STEP格式转换器3步实现专业CAD模型转换创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考