


修改 C++ 分析型数据库引擎,并跑完所需的测试
在修改用 C++ 编写的分析型数据库引擎代码时使用。AI 会沿着从 SQL 解析到执行的流程找到要改的地方,通过生成源修改生成文件,遵守 C++ 写法和错误处理的规则,并在跑完 SQL 逻辑测试和所有必需的构建后才算完成。
要使用这个AI规则
## 按工作阶段选择构建类型和要跑的测试
选择能够提供有效断言和诊断信息,同时不会让日常迭代变得过慢的构建配置。
### 构建策略
- 当带调试符号的优化构建能够保留必要检查时,将其用作常规开发配置。
- 调查内存安全、断言失败或可能受优化影响的行为时,使用启用完整检测功能的调试构建。
- 提交前运行仓库的格式化工具。
- 通过获准的生成目标重新生成源文件派生的文件,该目标还应执行必要的格式化。
### 测试策略
- 日常迭代期间运行快速单元测试套件。
- 诊断范围明确的变更时,将单次运行限定在一个测试文件或测试用例。
- 如果变更可能影响共享行为,在大范围交接前运行包含慢速测试的完整套件。
- 修复持续集成故障时,按照文档规定的顺序复现每项必要配置。
- 当受影响的边界需要时,加入配置矩阵、向量化执行、清理器和断言构建。
- 没有证据证明差异无关时,不得用更快的本地配置替代失败的权威关卡。
## 修改前,追踪查询从 SQL 解析到返回结果的流程
沿完整的查询生命周期追踪行为,不要只修补最先暴露症状的模块。
### 管道阶段
1. 将 SQL 文本解析为语句、表达式和表引用语法树。
2. 创建逻辑计划时,根据目录绑定名称和类型。
3. 使用保持语义的规则和基于成本的选择优化逻辑计划。
4. 将逻辑运算符转换为物理运算符。
5. 通过向量化并行管道执行物理运算符。
6. 通过连接和客户端上下文返回结果。
### 组件所有权
- 保持语法与解析器转换同步;每条语法规则都需要相应的转换。
- 由规划器负责绑定、类型解析、子查询和逻辑运算符。
- 由优化器在不改变可观察语义的情况下转换计划。
- 由执行层负责物理规划、运算符和表达式求值。
- 将持久存储、缓冲、压缩、检查点和预写日志保留在存储层。
- 将目录视为模式、表、函数和类型的唯一事实来源。
- 将事务、撤销状态和多版本并发控制与任务调度和并行管道分开。
## 按列批量处理数据,并遵守所有权规则
分析引擎依赖于对已解析语法、已绑定表达式、列标识、物理向量和所有权的清晰区分。
### 数据流
- 以列式批次而非逐行方式处理数据。
- 使用引擎的向量抽象表示每个批次列。
- 在规划和执行期间传递一对稳定的表索引与列索引。
- 让已解析表达式保持未绑定,并与有类型的已绑定表达式分离。
- 通过向量化表达式执行器计算已绑定表达式。
### 所有权和类型
- 默认使用独占智能所有权。
- 只有多个生命周期确实需要时,才使用共享所有权。
- 区分可为 null 的非拥有引用与保证非 null 的引用。
- 绝不使用拥有所有权的裸指针。
- 通过一套权威规则处理类型提升和强制转换。
- 通过扩展机制添加自定义类型,不要绕过类型系统。
- 使用访问者遍历树,使用工厂进行反序列化,并对运算符、条目和表达式层次结构使用有类型的子类。
## 在生成源中修改扩展和生成文件
将树内扩展、外部维护的扩展、生成代码和发布工件视为不同的所有权类别。
### 扩展边界
- 直接在声明的源目录中编辑树内扩展。
- 将外部维护的扩展放在单独的仓库中,并通过指定的补丁机制应用由仓库负责的变更。
- 同时支持构建完整扩展集和明确指定的子集。
- 按照内置功能使用的同一组核心接口和类型规则测试扩展变更。
### 生成工件
- 找出用于生成 API 绑定、注册、设置、序列化代码、存储元数据、指标和枚举工具的源文件。
- 编辑生成工件的源文件,绝不能只编辑生成结果。
- 更改源文件后运行获准的生成目标。
- 检查生成的差异是否存在无关改动,并使用标准格式化工具处理。
## 遵循 C++ 写法规则,保持注释简短
底层代码的一致性可以减少所有权、索引、公共接口和控制流方面的歧义。
### 代码风格
- 使用仓库的缩进和对齐规则,并通过格式化工具强制执行行宽限制。
- 优先使用固定宽度整数类型,而不是依赖平台的整数宽度。
- 对偏移量、索引和计数使用项目指定的索引类型。
- 通过常量引用传递非简单的只读对象。
- 当基于范围的循环能够清楚表达遍历时,优先使用它。
- 条件语句和循环始终使用花括号。
- 绝不使用 `const_cast`。
- 遵循既有的文件、类型、变量和函数命名约定。
### 注释
- 保持注释简短,让清晰的代码承担常规说明。
- 注释长期有效的意图、约束或不明显的不变量。
- 不要在代码中保留特定问题的修复历史。
- 将差一错误修复等变更叙述放在变更说明或提交消息中。
- 只有无法通过代码结构和命名说明不变量时,才使用较长的注释。
## 按错误类型选择异常或断言,并编写 SQL 逻辑测试
根据查询必须终止、可以恢复还是遇到程序员造成的内部缺陷来选择错误通道。
### 错误策略
- 对解析错误、对象缺失或内存耗尽等会终止查询的故障使用异常。
- 对同一查询期间可以恢复的情况使用返回值。
- 对用户输入绝不能触发的程序员错误使用调试断言。
- 让断言足够具体,以揭示被违反的不变量。
- 不要将预期的无效输入转变为内部断言失败。
### SQL 逻辑测试
- 对查询行为,优先使用声明式 SQL 逻辑测试,而不是 C++ 测试。
- 分别标记必须成功的语句和必须失败的语句。
- 声明查询所预期的结果列类型。
- 使用框架的规范分隔符分隔查询文本和预期行。
- 只有在具体措辞有意保持不稳定时,才对错误文本使用正则表达式预期。
- 明确声明所需的环境变量。
- 为慢速测试添加框架的慢速测试标记,使默认运行保持实用。
- 除正常路径外,还要覆盖数值、字符串和嵌套类型,以及无效和意外的用法。
- 提交前要求完整的权威测试套件通过。
## 从测试找到要改的地方,跑完所有必需的检查后再完成
编辑前使用测试和架构所有权定位功能,然后验证受变更影响的每个派生表面。
### 调查顺序
1. 查找现有测试,了解受支持的语法和预期行为。
2. 从解析器开始,经由绑定器、优化器和物理规划,追踪功能直至执行阶段。
3. 找到相应的语句、运算符、表达式、目录或函数类型。
4. 检查功能的注册位置及其公共声明所在位置。
5. 使用仓库的标准代码搜索工具搜索实现文件和公共头文件。
6. 找出依赖已变更源文件的生成文件和扩展表面。
### 完成检查
- 在大范围测试前添加或更新重点回归测试。
- 运行格式化和源文件生成。
- 先运行重点测试,再运行所需的单元、慢速、清理器、断言、配置和向量测试套件。
- 构建受影响的可执行文件和扩展。
- 检查生成差异和文档所有权。
- 在每个必要关卡都取得实际结果之前,不得声称完成。
