- 数据库
- 桌面应用
- 开发工具
【免费下载链接】Sequel-Ace
MySQL/MariaDB database management for macOS
SPMySQL.framework 是 Sequel-Ace(macOS 平台上的 MySQL/MariaDB 数据库管理客户端)底层核心网络框架,它以文本 SQL 查询为输入、以“MySQL 原生类型 → Cocoa 对象”的自动转换为输出,为桌面应用提供了一条稳定、可流式读取结果集的数据库连接链路。本文基于 Frameworks/SPMySQLFramework/README.md 与其 Source 目录下的完整源码,系统讲解该框架的定位、能力清单、Xcode 集成步骤以及连接、查询、结果集处理三大核心 API 的实战用法,帮助你在自己的 macOS 项目中快速复用它。
框架定位:连接、查询、类型转换三合一的 MySQL 客户端层
SPMySQL.framework 的目标非常明确:提供一个稳定的 MySQL 连接框架,能够执行文本查询,并快速取回结果集,同时把 MySQL 数据类型转换为 Cocoa 对象。在 Sequel-Ace 的架构中,它位于 Source 的业务层与 C 语言 MySQL 客户端库(见 Frameworks/libmysqlclient)之间,承担了所有与服务器通信的底层工作。
值得说明的是,SPMySQL.framework 的接口“松散地”参考了 Serge Cohen 与 Bertrand Mansion 的 MCPKit(MySQL-Cocoa 项目),尤其借鉴了 Sequel Pro 深度改造的版本,但整个框架是一次完整的重写(full rewrite),并非对原框架的简单移植。同时它吸收了一批由 Hans-Jörg Bibiko、Stuart Connolly、Jakob Egger 与 Rowan Beentje 等开发者贡献的功能补丁,这些补丁后来构成了框架的核心能力清单。
核心能力清单:从连接锁到几何类型的一整套工程化方案
README 明确列出了框架继承自 Sequel Pro 补丁的 15 项能力,它们正是框架“稳定、快速”的工程支柱。下表逐项列出能力、贡献者与对应的源码文件,便于对照研读:
| 能力 | 主要贡献者 | 对应源码 |
|---|---|---|
| 连接锁定(Connection locking) | Jakob et al. | Locking.h,基于NSConditionLock防止非线程安全的查询误用 |
| Ping 与保活(Ping & keepalive) | Rowan et al. | Ping & KeepAlive.h、SPMySQLKeepAliveTimer.h |
| 查询取消(Query cancellation) | Rowan et al. | cancelCurrentQuery,见 Querying & Preparation.h |
| 委托设置(Delegate setup) | Stuart et al. | SPMySQLConnectionDelegate.h |
| SSL 支持(SSL support) | Rowan et al. | useSSL及证书路径属性,见 SPMySQLConnection.h |
| 连接检查(Connection checking) | Rowan et al. | checkConnection/checkConnectionIfNecessary,见 SPMySQLConnection.h |
| 版本状态(Version state) | Stuart et al. | serverVersionNumber/isMariaDB,见 SPMySQLConnection.h |
| 最大数据包大小控制(Max packet size control) | Hans et al. | Max Packet Size.h,对应max_allowed_packet |
| 结果集多线程与流式读取(Result multithreading & streaming) | Rowan et al. | SPMySQLStreamingResult.h、SPMySQLFastStreamingResult.h |
| 编码支持与切换(Encoding support & switching) | Rowan et al. | Encoding.h |
| 数据库结构移入应用层 | Hans et al. | 由宿主应用接管 schema 管理,框架专注连接与查询 |
| 查询重试与错误处理策略 | Rowan et al. | retryQueriesOnConnectionFailure,见 SPMySQLConnection.h |
| 几何结果类(Geometry result class) | Hans et al. | SPMySQLGeometryData.h |
| 连接代理(Connection proxy) | Stuart et al. | SPMySQLConnectionProxy.h,配合 Delegate & Proxy.h |
从源码结构看,这 15 项能力被组织为SPMySQLConnection上的 9 个公开分类(Category)与结果集体系,整体 API 入口集中在 SPMySQL.h 这一个头文件中,方便外部统一#import。
工程集成:以子项目方式接入 Xcode 的五步流程
README 给出了两种集成方式:作为标准 Cocoa framework 直接链接,或者把整个工程作为子项目(subproject)嵌入你的 Xcode 工程。后者是 Sequel-Ace 自身的做法,操作步骤如下:
- 把 SPMySQL framework 的 SPMySQLFramework.xcodeproj 拖入你的当前工程;
- 选中某个已有 target,打开 Get Info 面板,在“Direct Dependencies”中添加新依赖,从子项目中选择
SPMySQL.frameworktarget; - 展开子项目,将其子 target
SPMySQL.framework拖入使用该框架的 target 的Link Binary With Libraries构建阶段; - 若当前工程没有 Copy Frameworks 阶段,则新建一个,并把
SPMySQL.framework子 target 拖入该阶段(保证运行时能复制到 App 包内); - 在 Build Settings 中添加User Header Search Path,设置为指向 SPMySQL 工程目录的递归路径,例如
${PROJECT_DIR}/Frameworks/SPMySQLFramework。完成之后,你就能在代码里#include "SPMySQL.h"并正常使用全部 API。
说明:
${PROJECT_DIR}是 Xcode 内建变量,指向project.pbxproj所在目录;上述路径正是 Sequel-Ace 当前仓库中的实际位置。框架编译依赖的 MySQL 客户端库位于 Frameworks/SPMySQLFramework/MySQL Client Libraries/lib,链接阶段需保证可用。
连接生命周期:从建立到断开的完整状态机
SPMySQLConnection是框架的核心类,SPMySQLConnection.h 中定义了它的全部配置项与状态。连接状态由 SPMySQLConstants.h 中的枚举描述:
SPMySQLDisconnected = 0, // 已断开 SPMySQLConnecting = 1, // 连接中 SPMySQLConnected = 2, // 已连接 SPMySQLConnectionLostInBackground = 3, // 后台连接丢失 SPMySQLDisconnecting = 4 // 正在断开基础连接参数
连接需要配置以下属性(均见 SPMySQLConnection.h):
| 属性 | 类型 | 说明 |
|---|---|---|
host | NSString | 服务器地址 |
username/password | NSString | 认证凭据 |
port | NSUInteger | 端口号 |
useSocket+socketPath | BOOL / NSString | 使用 Unix Socket 而非 TCP 连接 |
database | NSString | 默认选中的数据库 |
timeout | NSUInteger | 连接超时(秒),源码默认值为 30 |
useKeepAlive+keepAliveInterval | BOOL / CGFloat | 是否启用保活及间隔(秒),源码默认间隔为 60 |
maxQuerySize | NSUInteger | 单条查询允许的最大字节数,默认 1048576(约 1 MB) |
clientFlags | SPMySQLClientFlags | 客户端能力标志,可组合 |
其中clientFlags支持在 SPMySQLConstants.h 定义的标志位中叠加或移除:
SPMySQLClientFlagCompression = 32, // CLIENT_COMPRESS:压缩传输 SPMySQLClientFlagInteractive = 1024, // CLIENT_INTERACTIVE:交互式会话 SPMySQLClientFlagMultiResults = (1UL << 17) // CLIENT_MULTI_RESULTS:多结果集通过addClientFlags:/removeClientFlags:方法动态调整。
连接建立与断开
SPMySQLConnection *connection = [[SPMySQLConnection alloc] init]; connection.host = @"127.0.0.1"; connection.username = @"root"; connection.port = 3306; connection.useSSL = YES; BOOL ok = [connection connect]; // 建立连接 BOOL alive = [connection isConnected]; // 查询连接状态 [connection disconnect]; // 主动断开(userTriggeredDisconnect 置 YES)连接丢失时,框架会进入“后台连接丢失”状态并触发重连决策——决策逻辑由委托协议控制,详见下文。
SSL 与加密细节
连接支持useSSL及三份证书路径属性(密钥、客户端证书、CA 证书),并可传入sslCipherList指定 TLS 1.3 之前版本的密码套件(冒号分隔,顺序即优先级,默认值为 nil 表示使用框架内建列表)。源码 SPMySQLConnection.m 显示:TLS 1.3 密码套件则通过MYSQL_OPT_TLS_CIPHERSUITES独立配置,使用内建的_defaultTLSSuiteListString,且当前不被sslCipherList覆盖。
另外,连接还提供requestServerPublicKey属性:当使用caching_sha2_password认证且连接未走 TLS时,请求服务器公钥以完成密码交换(见 SPMySQLConnection.m)。
委托协议:连接事件的观察者与决策者
SPMySQLConnectionDelegate协议(SPMySQLConnectionDelegate.h)是接入框架业务逻辑的主要入口,所有方法均为@optional:
willQueryString:connection::每条查询发送前回调,可用于查询日志;queryGaveError:connection::查询出错时回调;showErrorWithTitle:message::框架要求委托直接向用户展示错误;keychainPasswordForConnection::按需从安全存储(如 Keychain)取回密码,避免把明文密码放在连接对象上;noConnectionAvailable::底层连接完全不可用时通知委托;connectionFellBackToNonSSL::请求了 SSL 但服务器最终以非 SSL 方式连接时通知;connectionLost::连接临时丢失时询问委托如何决策,返回值类型为:
SPMySQLConnectionLostDisconnect = 0, // 直接断开 SPMySQLConnectionLostReconnect = 1 // 尝试重连README 明确指出:如果委托未实现connectionLost:,框架将自动尝试重连,但次数有一个较小的上限(源码中对应reconnectionRetryAttempts与lastDelegateDecisionForLostConnection字段)。此外,连接还支持setProxy:注入SPMySQLConnectionProxy,实现连接级代理(如通过 SSH 隧道转发 TCP 流量)。
查询执行:四种结果模式与编码切换
查询 API 全部集中在 Querying & Preparation.h,围绕queryString:家族展开。
查询入口与结果类型
核心方法是带编码与返回类型参数的统一入口:
- (id)queryString:(NSString *)theQueryString usingEncoding:(NSStringEncoding)theEncoding withResultType:(SPMySQLResultType)theReturnType;SPMySQLResultType定义于 SPMySQLConstants.h,决定结果集的四种形态:
SPMySQLResultAsResult = 0, // 标准 SPMySQLResult(一次性全量取回) SPMySQLResultAsFastStreamingResult = 1, // 快速流式结果 SPMySQLFastStreamingResult SPMySQLResultAsLowMemStreamingResult = 2, // 低内存阻塞流式结果 SPMySQLResultAsStreamingResultStore = 3 // 流式结果仓库 SPMySQLStreamingResultStore为方便日常使用,框架提供了三个便捷入口:
// 全量取回:返回 SPMySQLResult SPMySQLResult *result = [connection queryString:@"SELECT * FROM users"]; // 快速流式:返回 SPMySQLFastStreamingResult,边取边处理 SPMySQLFastStreamingResult *fastResult = [connection streamingQueryString:@"SELECT * FROM big_table"]; // 流式结果仓库:返回 SPMySQLStreamingResultStore,可随机访问已缓冲数据 SPMySQLStreamingResultStore *store = [connection resultStoreFromQueryString:@"SELECT * FROM report"];“快速取回结果集”正是通过后两种流式模式实现的——它们适合处理大结果集,避免一次性把整表数据载入内存。
数据准备:转义与防注入
框架内置了完整的字符串/二进制转义 API,用于安全拼接 SQL:
- (NSString *)escapeAndQuoteString:(NSString *)theString; // 转义并加单引号 - (NSString *)escapeString:(NSString *)theString includingQuotes:(BOOL)includeQuotes; - (NSString *)escapeAndQuoteData:(NSData *)theData; // 转义二进制数据 - (NSString *)escapeData:(NSData *)theData includingQuotes:(BOOL)includeQuotes;查询前务必对用户输入执行转义,防止 SQL 注入。框架在头文件中还提供了SPMySQLConnectionEscapeString、SPMySQLConnectionEscapeData、SPMySQLConnectionQueryString三个带缓存 selector 的静态内联函数,用于高频调用场景下的性能优化。
查询信息与错误状态
执行后可通过以下方法获取元信息(见 Querying & Preparation.h):
- (unsigned long long)rowsAffectedByLastQuery; // 受影响行数 - (unsigned long long)lastInsertID; // 自增插入 ID - (BOOL)queryErrored; // 是否出错 - (NSString *)lastErrorMessage; // 错误信息 - (NSUInteger)lastErrorID; // 错误码 - (NSString *)lastSqlstate; // SQLSTATE + (BOOL)isErrorIDConnectionError:(NSUInteger)theErrorID; // 判断错误码是否属于连接类错误超限保护与查询取消
框架针对 MySQL 的max_allowed_packet做了封装:Max Packet Size.m 通过查询服务器端max_allowed_packet值自动校准maxQuerySize,若查询字节数超过限制会给出本地化错误提示,并在允许时(maxQuerySizeIsEditable)动态调整。同时cancelCurrentQuery提供查询取消能力,配合lastQueryWasCancelled属性判断查询是否被主动取消。
结果集处理:从全量结果到流式消费与类型转换
结果集体系由SPMySQLResult及两个流式子类构成,顶层接口见 SPMySQLResult.h。
行数据读取模式
SPMySQLResult实现NSFastEnumeration,可直接用for...in遍历;也支持按目标行类型取行,SPMySQLResultRowType定义于 SPMySQLConstants.h:
SPMySQLResultRowAsDefault = 0, // 实例默认格式 SPMySQLResultRowAsArray = 1, // NSArray SPMySQLResultRowAsDictionary = 2 // NSDictionary(以字段名为键)常用读取 API:
- (NSArray *)fieldNames; // 字段名数组 - (void)seekToRow:(unsigned long long)targetRow; // 定位到指定行 - (id)getRow; // 按默认类型取一行 - (NSArray *)getRowAsArray; - (NSDictionary *)getRowAsDictionary; - (id)getRowAsType:(SPMySQLResultRowType)theType;returnDataAsStrings属性可以强制所有字段以字符串返回,对某些老版本服务器返回的 SHOW 命令结果(如SHOW CREATE TABLE、SHOW VARIABLES)尤其必要。快速遍历可借助头文件提供的SPMySQLResultGetRow静态内联函数。
字段处理器与 MySQL 类型映射
框架通过SPMySQLResultFieldProcessor枚举(SPMySQLResult.h)区分字段处理策略:
SPMySQLResultFieldAsUnhandled = 0, SPMySQLResultFieldAsString = 1, SPMySQLResultFieldAsStringOrBlob = 2, SPMySQLResultFieldAsBlob = 3, SPMySQLResultFieldAsBit = 4, SPMySQLResultFieldAsGeometry = 5, SPMySQLResultFieldAsNull = 6SPMySQLDataTypes.h 则罗列了框架认识的全部 MySQL 类型常量,覆盖数值(SPMySQLTinyIntType…SPMySQLBigIntType)、浮点(SPMySQLFloatType/SPMySQLDoubleType)、字符串(SPMySQLCharType/SPMySQLVarCharType)、TEXT/BLOB 家族、SPMySQLEnumType/SPMySQLSetType、日期时间家族、几何类型家族(SPMySQLGeometryType/SPMySQLPointType等)以及SPMySQLJsonType、SPMySQLInet4Type/SPMySQLInet6Type——这就是“MySQL 数据类型到 Cocoa 对象转换”的完整映射表,转换逻辑集中在 SPMySQLResult Categories/Data Conversion.m。
流式结果:低内存消费大结果集
- SPMySQLStreamingResult.h:逐行从服务器拉取、随取随弃的基础流式结果;
- SPMySQLFastStreamingResult.h:快速流式版本,适合需要尽快消费的场景;
- SPMySQLStreamingResultStore.h + SPMySQLStreamingResultStoreDelegate.h:把流式结果缓冲到存储中并支持随机访问,适合导出、分页等需要“先全部收下、再按需读取”的场景。
空结果集由 SPMySQLEmptyResult.h 表示,避免为无数据查询分配无意义的结果对象。几何字段则以 SPMySQLGeometryData.h 承载,这正是 README 中“Geometry result class”能力的落点。
编码、时区与服务器信息:正确性相关的辅助能力
- 编码支持与切换:Encoding.h 允许按连接设定字符集,并记录
encoding/encodingToRestore与previousEncoding以支持来回切换;框架还处理 Latin-1 传输的特殊分支(encodingUsesLatin1Transport)。 - 时区:
updateTimeZoneIdentifier:可同步连接的时区标识,timeZoneIdentifier为只读属性(见 SPMySQLConnection.h)。 - 服务器信息:Server Info.h 提供版本号解析与 MariaDB 识别(
isMariaDB、isNotMariadb103),Sequel-Ace 借此区分 MySQL 与 MariaDB 的语法差异。 - 保活与超时:Ping & KeepAlive.m 依据
lastConnectionUsedTime与lastKeepAliveTime判断是否需要发送保活 ping;若服务器允许,也可通过_queryMaxAllowedPacketWithSQL动态放大单包上限。
测试与质量保障
仓库 Frameworks/SPMySQLFramework/SPMySQL Unit Tests 目录下的测试直接覆盖了本文讲解的若干能力,可作为学习与验证的样例:
- DataConversion_Tests.m:验证 MySQL 类型到 Cocoa 对象的转换;
- SAByteStringDecoderTests.swift:验证二进制字节串解码;
- SADatabaseAssertionTests.swift:验证
assertingDatabase:/assertingDatabaseContext:系列的数据库上下文断言行为; - SPMySQLStringAdditions_Tests.m:验证转义与字符串处理。
其中SADatabaseAssertion(SADatabaseAssertion.swift)是 Sequel-Ace 在框架基础上新增的数据库状态守卫:assertingDatabase:变体保留“nil 表示无断言”的旧行为,而assertingDatabaseContext:变体把 nil 视为“显式断言当前未选中任何数据库”,防止多窗口/多连接场景下查询落到错误的数据库上——这是从源码注释中可以直接读到的设计意图。
许可与使用约束
SPMySQL.framework 遵循 MIT 许可(版权归属于 Rowan Beentje 与 Sequel Pro 团队,2018),完整条款见 Frameworks/SPMySQLFramework/LICENSE,可自由集成、修改与再分发,并需保留版权声明。在 Sequel-Ace 主工程中,它通过与 Frameworks/SPMySQLFramework/MySQL Client Libraries 下的客户端库配合使用,这也是集成第 5 步中“递归头文件搜索路径”之所以必要的原因——SPMySQL.h会通过<SPMySQL/...>形式引用框架内全部公开头文件(见 SPMySQL.h)。
总结:SPMySQL.framework 以“稳定连接 + 文本查询 + 类型转换”三个支点覆盖了 macOS 桌面应用访问 MySQL/MariaDB 的完整链路。无论你只是想在自有 Cocoa 工程里快速跑通connect→queryString:→ 遍历结果集的最小闭环,还是需要借助流式结果、SSL、保活重连、委托决策等机制构建生产级数据库客户端,都可以直接参考本文的 API 说明与源码路径深入实现细节。
- 数据库
- 桌面应用
- 开发工具
【免费下载链接】Sequel-Ace
MySQL/MariaDB database management for macOS
相关推荐
CANN/asc-devkit向量小于比较API
asc_lt 产品支持情况 | 产品 | 是否支持 | | : | : :| | <cann filter npu_type="950" <term Ascen
人工智能深度学习算子库CANNAscendEMQX Oracle 数据库连接器(emqx_oracle)深度解析:连接管理、SQL 模板与数据桥接实战
EMQX Oracle 数据库连接器(emqx_oracle)深度解析:连接管理、SQL 模板与数据桥接实战 导读 本文围绕 EMQX 仓库中的 Oracle
后端物联网消息队列通信Swift 数值类型与 `NSNumber`、Cocoa 结构体与 `NSValue` 桥接:SE-0139 全面解析
Swift 数值类型与 NSNumber 、Cocoa 结构体与 NSValue 桥接:SE 0139 全面解析 SE 0139(《Bridge Numeric
文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考