diff --git a/.agents/README.md b/.agents/README.md index 9fe1721..59fe3a4 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -1,6 +1,10 @@ # AI agent 协作资料 -按任务读取,不将全部资料作为每次工作的上下文。 +本页帮助 AI agent 选择任务所需资料。按任务读取,不将全部资料作为每次工作的上下文。 + +## 资料入口 + +各文件的职责如下: - 根目录 `AGENTS.md`:开发规则和测试入口。 - `context/progress.txt`:唯一进度、测试计数和验收来源。 @@ -8,6 +12,10 @@ - `context/main-roadmap.txt`:长期阶段;`side-branch-plan.txt`:近期任务及依赖。 - `skills/chusql-*/`:类型、存储、跨组件边界三个项目专用技能。 +## 文档与技能 + +文档写作使用全局 `technical-documentation` 和 `plain-writing`,具体规则见根目录 `AGENTS.md` 的“文档编写”一节。 + 通用技能、安装锁文件及技能生成提示词仅保留在本地,不纳入版本控制。 `gate-check/` 为开发者和 CI 共用的门禁工具;`logs/` 为忽略的本地产物。 这些协作资料不参与应用构建、运行或发行打包。 diff --git a/.agents/context/design-decisions.txt b/.agents/context/design-decisions.txt index 3a03b8d..335bd8b 100644 --- a/.agents/context/design-decisions.txt +++ b/.agents/context/design-decisions.txt @@ -2,66 +2,142 @@ 进度见 progress.txt,限制见 known-issues.txt,用户操作见 docs/。 ## 架构与接口 -- 用户文档按主题记录于 docs/commands.md、docs/types.md、docs/architecture.md 和 docs/install.md;只读范式入口已提供。后续实施 bound IR / DOMAIN,再推进物化、递归、MVCC、compact 和并行写;规划不代表现有能力。 + +### 文档与后续方向 + +- 用户文档按主题记录于 docs/commands.md、docs/types.md、docs/architecture.md 和 docs/install.md;只读范式入口已提供。 + + 后续完善绑定后的中间表示(bound IR)与 DOMAIN,扩展物化资源控制、递归查询,并按实测减少行版本发布与在线整理的开销;规划不代表现有能力。 - 范式迁移首版保留来源,拒绝 NULL、重复行与依赖不保持;发布目标须验证约束、完整重建并使用独立原子结构 WAL 组,不能复用禁止 DDL 的会话事务拼接执行。 -- 发布真实性采用 TUF 元数据链与 Ed25519,初始 root 必须可信取得;离线验证不证明最新版本,操作系统原生代码签名另行接入。 +- 发布真实性规划采用 TUF(用于验证软件更新元数据的框架)与 Ed25519 签名;初始 root 信任元数据必须可信取得,离线验证不证明最新版本。操作系统原生代码签名另行接入;这些签名能力尚未实现。 + +### 组件边界与分层 + - Web / CLI → server TCP → Haskell 引擎 → FFI → Rust 存储;server 独占数据目录,Haskell 库静态链接,存储为 cdylib。 - 引擎按 AST → 语义检查 → RelOp → 优化 → 执行分层;语义与优化只读 schema,表存在性以 catalog 为准,索引由存储管理。 -- JSON 使用显式稳定标签,FFI 仅提供 version / open / close / request / free / last_error;Web 不本地执行 SQL。 +- JSON 使用显式稳定标签,FFI 提供 version / open / close / request / maintenance / free / last_error;Web 不本地执行 SQL。 + +### 类型语义的职责 + - 兼容值与类型语义集中于 Core.Model,运行时类型与版本化编码集中于 Core.Runtime,函数注册与绑定集中于 Engine.Runtime;旧运算符保留 Engine.Builtin,错误分类集中于 Engine.Error。 - 比较与赋值兼容性分开,整数与整值浮点统一相等和哈希,SQL NULL 比较走三值逻辑;DML 的 CHECK 随写计划一次绑定,结构变更对新 schema 重新绑定。 + +### 写入求值与约束 + - 写表达式和 CHECK 复用查询的列槽位绑定及行布局整理,避免按物理返回顺序取错值;UPDATE 在执行前按 schema 一次绑定目标槽位及列定义,按槽位校验、转换并覆盖单个值。目标不存在或歧义明确失败,不保留缺失类型时直接写入的兜底;保留逐项赋值、全部赋值后的 CHECK 及未命中行不求值。 - INSERT 目标清单拒绝重复列,合法目标在本次执行中一次映射到 VALUES 槽位;行构造保留 schema 顺序及原输入表达式求值顺序,默认值、自增、显式 NULL 和整批校验沿用既有语义。缺少已绑定输入值明确失败,不把它作为省略列处理。 - UPDATE 在全部行求值及 CHECK 成功后、调用存储写入前,复用 INSERT 的 NOT NULL 和 UNIQUE / PRIMARY KEY 检查;唯一性以最终整表结果判断,多个 NULL 不冲突。约束失败不发布部分行修改,事务快照保留并允许修正后继续提交。 -- NOT NULL 和 UNIQUE / PRIMARY KEY 检查使用 schema 位置绑定列,缺值或位置不符明确失败,不用 mapMaybe 跳过缺列。INSERT 的已有行与经引擎重写 schema 的 ALTER 输入行在约束边界按原 schema 整理;保留列级错误顺序、NULL 去重规则和数值规范化比较。 -- 写语句及已有表 DDL 使用仅保存 schema 的 BoundWrite,复用查询的依赖验证规则;收集目标、嵌套查询和传递 DOMAIN,新增列或改类型包含新声明 DOMAIN。先以只读 validate_write 确认写守卫能力,再发送实际写入;存储按库名排序取门,在目标库独占门及其他依赖共享门内复查后执行,不改变单次请求之间的数据隔离语义。 +- NOT NULL 和 UNIQUE / PRIMARY KEY 检查使用 schema 位置绑定列,缺值或位置不符明确失败,不用 mapMaybe 跳过缺列。 + + INSERT 的已有行与经引擎重写 schema 的 ALTER 输入行在约束边界按原 schema 整理;保留列级错误顺序、NULL 去重规则和数值规范化比较。 + +### 写计划与结构守卫 + +- 写语句及已有表 DDL 使用仅保存 schema 的 BoundWrite,复用查询的依赖验证规则;收集目标、嵌套查询和传递 DOMAIN,新增列或改类型包含新声明 DOMAIN。 + + 先以只读 validate_write 确认写守卫能力,再发送实际写入;存储按库名排序取门,在目标库独占门及其他依赖共享门内复查后执行,不改变单次请求之间的数据隔离语义。 - BoundWrite 的 DML 动作保存 INSERT 输入槽位、UPDATE 赋值目标、DELETE 布局和预绑定 CHECK / 非空 / 唯一性约束,执行期不再重新解析或按名称绑定目标;自动编号仍从当前行集求起点,唯一性仍按最终行集校验,保持逐项赋值及未命中行不求值。 - CHECK 定义与执行共用布尔条件、函数和槽位绑定;聚合及子查询拒绝。结构变更先按新 schema 校验保留约束、默认值及键能力,空表不跳过;CHECK 文本未采用独立列身份,改名不自动重写,失效引用明确拒绝。 ## 查询与优化 + +### 优化与成本选择 + - 优化保持结果语义和可观察行序;相关外层列不能被投影删除,LEFT JOIN 只下推安全的左侧谓词。 - schema 携带行数、distinct、索引和直方图,缺统计时保守退回原计划。范围成本使用 16 桶等宽直方图,无直方图时按四分之一估算。 - 内连接从各起点贪心选序,仅在严格更省且行序不可观察处重排;统计不足或不安全条件时不改写。 + +### 名称与作用域 + - 表 / 列限定名在语义层按作用域及唯一候选解析,别名优先;会话将当前库限定 DDL 转为裸名,拒绝跨库目标,库名随请求传递。 - 相关子查询的语义列环境按词法层逐层查找,保留最近层的列及类型,不把不同外层并成一张表;本层歧义不向外回退。JOIN ON 和外部引用收集使用同一外层环境,来源检查失败明确传播。执行期仍使用既有扁平外层行布局。 - SELECT 在引擎入口直接进入 BoundQuery,避免规范化引用再次作为原始来源名解析;二段限定名被最近层同名来源遮蔽,该来源缺列时不回退。裸列仍按列可见性逐层查找,已解析引用的类型推导不重新解释来源遮蔽。 + +### 列槽位与重绑定 + - 绑定后的子查询保存父布局中的局部或外层列槽位,取值与复用缓存键共享该绑定;诊断名称相同不表示位置相同。重绑定不把外层引用转为局部引用,布局失配和引用清单失配明确返回错误;原始关系执行 API 保留未绑定 Subquery 的名称入口。 - 已绑定列重绑定时保留仍匹配名称的有效位置,原位置不匹配仅允许唯一同名列重定位;歧义或负位置拒绝。外层槽位保留相对位置并更新局部宽度;独立列身份未实现,结构改写仍须在绑定前完成,不能凭同名槽位识别重排后的不同列。 - 相关子查询保留已解析外层限定名;求值绑定补回单表物理列的限定名,绑定去重与扫描投影使用同一列值,库限定引用仍校验 schema 来源。 + +### 子查询执行与复用 + - JOIN 条件按子查询外层引用的值缓存替换后的表达式;首次遇到行对时才求值,每个行对仍计算普通条件,保留输出顺序、空输入和错误返回。 -- 半连接仅重写独立 IN 或单表唯一等值相关 EXISTS 的单独过滤谓词;键按两侧布局分别绑定,输出只保留原左行。独立 IN 沿用物化身份,NOT IN 感知右侧 NULL,反 EXISTS 保留空值键;大数混合比较退回原比较语义。复杂条件、可能报错的相关投影和相关聚合不重写,空左侧不执行右侧,保持完整右侧求值;空集 IN 为假、NOT IN 为真(含 NULL 左值),非空集合保持三值逻辑。 +- 半连接仅重写独立 IN 或单表唯一等值相关 EXISTS 的单独过滤谓词;键按两侧布局分别绑定,输出只保留原左行。独立 IN 沿用物化身份,NOT IN 感知右侧 NULL,反 EXISTS 保留空值键;大数混合比较退回原比较语义。 + + 复杂条件、可能报错的相关投影和相关聚合不重写,空左侧不执行右侧,保持完整右侧求值;空集 IN 为假、NOT IN 为真(含 NULL 左值),非空集合保持三值逻辑。 - 每次查询执行用独立状态物化成功行集,子查询按已解析定义和具名外层绑定值共享,原始名称调用保守包含整个外层行;派生表按执行子树和外层行缓存,先共享再应用别名。各消费者独立处理标量基数与三值逻辑,失败仍明确返回,保持既有求值顺序;不跨执行保留,也不提供整条查询快照或磁盘溢出。 + +## 存储提交前校验 + - WAL 提交组落盘后、首次应用前进入 recovery_required;任何应用、刷盘或检查点错误都保持该状态,完整落盘与截断成功后才解除。 +- 普通提交组在分配对象编号及写 WAL 前,使用 HeapTable::encode_row 检查全部载荷行;单写、批写、整表替换、事务及结构重写共用此边界,避免可预见的行大小错误在提交后触发恢复封闭。账号专用 WAL 路径保留原有账号行预校验;不改变页格式与已有恢复顺序。 +- 索引键容量共用 DiskBTree::check_key,存储提交预检复用堆表实际键编码;结构替换只检查保留的内置 id 索引,删列重写排除已移除索引。建索引在写 WAL 前扫描目标列校验;堆表插入、建索引和整表替换在修改数据前检查键长,不用截断键或跳过错误降级。 +- 新插入 id 的冲突预检复用 row_key,在同库写门内按 WAL 操作顺序维护键计数;未涉及的现存键按需查询 id 索引,不为单次插入全表扫描。 + + 删除键在一条操作内去重且每键只减一,保留旧重复 id 的首行删除规则;整表替换重建预检基线,沿用其兼容重复 id 的行为。预检不改变恢复重放与原有页格式。 +- 目录预演覆盖普通写入可能触发的扩列及结构重写的载荷行,列推导与版本递增共用 Catalog::ensure_columns;只在结构操作或输入可能扩列时克隆目录。 + + 按行及操作顺序累计变化,在写 WAL 前拒绝版本耗尽,保留同一行多列只递增一次及未定型 NULL 不扩列的规则;已有列的数据写入不因版本达到上限而被拒绝。 +- Request::valid_columns 检查所有写入载荷的顶层字段名及事务内行,存储表名与列名字符集共用 valid_storage_name;保持已有非空 ASCII 字母、数字及下划线规则。 + + 只在请求边界约束新载荷,不递归检查值内部键,不对旧目录、堆行及 WAL 重放加新名称限制,也不静默改名或丢字段。 + +## 查询来源与排序 + - FROM 是来源树,派生表必须带别名且不能引用外层,输出取裸列名,重名报错;未定型 NULL 保留独立查询推导类型,不能声明为存储类型。 - ORDER BY 优先匹配唯一输出别名,再查来源列;只将排序表达式提前计算,非排序投影保持在 LIMIT 后求值。CTE 列清单同步重命名内层排序别名。 - ORDER BY 输出序号保留到计划生成,不转换为诊断名称;普通查询选定对应投影表达式,DISTINCT 按去重结果槽位排序,重复别名不丢失位置。名称排序仍拒绝歧义,序号不作为相关子查询自由列,排序键遵守类型能力、分组及 LIMIT 求值时序。 - 派生表从透明算子与 schema 统计估算行数,缺统计或表达式可能报错时不重排;投影下推保留计算项,避免删除错误。内存存储提供实时行数及封顶去重统计。 + +### 数值与子查询语义 + - DECIMAL(p,s) 使用有限浮点、ties-to-even 舍入和舍入后溢出检查,要求 1 <= p <= 308、0 <= s <= p;Haskell 与 Rust 写入入口统一边界,日志记录规范化值。 -- CTE 解析期展开为派生表,只接受 SELECT,不物化;多次引用重复执行,以减少实现改动面。 +- CTE 解析期展开为派生表,只接受 SELECT。相同执行子树在一次查询中物化复用;不同投影或优化后的子树仍分别执行,不支持递归或显式物化语法。 - 比较及 ANY / ALL 使用独立 AST 节点,量词复用三值逻辑,空集 ANY=false、ALL=true。 -- 子查询在 Filter / Compute 中按外层绑定分组复用,暂不引入半连接;扫描按页分片,至少 1000 行、最多 8 线程,结果保序,safe FFI 释放执行能力。 +- 子查询在 Filter / Compute 中按外层绑定分组复用;适用的独立 IN 与简单等值相关 EXISTS 使用半连接或反连接,复杂条件保留原路径。扫描按页分片,至少 1000 行、最多 8 线程,结果保序,safe FFI 释放执行能力。 ## 会话、事务与存储 + +### 会话快照与差分 + - 每连接独立会话及工作库;短锁取得库句柄后执行,每库读写门控制可见性,表锁保护页,在用库不强行删除。 - BEGIN 物化当前库快照,事务内走内存执行,COMMIT 提交相对基线差分,ROLLBACK 丢弃快照。 - COMMIT 先跳过数据未修改的表,整数 id 用 IntMap / IntSet 查找差异与冲突;保留原行顺序及重复 id 的首行查找语义,冲突检查和提交操作共享一次差分。 +- SQL 数据语句和提交使用共享全局门与共享库门;同库最终校验和发布使用单独的短提交门。自动提交也走事务计划、行锁和版本复查,保持失败不部分发布。权限与 DDL 全局独占,原始管理员存储写入通过版本变化参与冲突检查。 - 有整数 id 时按键提交及检查写写冲突,无整数 id 时整表比对;未修改表不回写,冲突保留事务并返回 serialization_failure。 +- COMMIT 在短提交门内预演实际事务操作,并复用引擎的领域 / CHECK / 非空 / 唯一性规则校验合并最终行集,避免不同整数主键绕过业务唯一约束;校验失败不写 WAL,事务保留。内存预演与存储一致,每个去重删除键只删除首个旧重复 id 行。 +- 可选 BEGIN [TRANSACTION] ISOLATION LEVEL SERIALIZABLE / START TRANSACTION ISOLATION LEVEL SERIALIZABLE 保留整库快照,在写事务提交时复查读写语句全部表的 schema 和行集,包含子查询与幻行;按表保守拒绝冲突,默认 BEGIN 的不同行差分合并不变。保存点恢复语句列表,也恢复读依赖;只读事务不因数据变化拒绝提交。 - 保存点保存不可变快照引用,同名取最近一层,回退 / 释放丢弃之后的点,结束清空;事务命令由会话层执行。 + +### 日志与恢复 + - WAL 先记录操作及提交标记,再应用、刷数据与 catalog、写检查点、截断;仅重放已提交且超过检查点的记录。 - WAL 帧保留长度、LSN、类型码、表名及 JSON payload,兼容旧记录;恢复按内容、schema 和文件存在性判断幂等。 - 检查点按库 LSN,前缀截断用同目录临时文件原子替换,未提交尾部直接截短;失败保留 WAL 并进入 recovery_required。 - 检查点采用同目录临时文件替换,长度必须为 8 字节;完整 WAL 帧损坏明确报错,尾部不完整帧保留撕裂处理。刷盘或检查点失败后封闭请求,重启重放已提交组。 + +### 统计与页面整理 + - distinct 在封顶前按值引用计数维护,列封顶不清除其他列状态;直方图独立累计与递减,桶重映射导致删除目标为空时扣最近非空桶以保持总量。rebuild_stats 先扫描数值范围,再按固定边界计数,消除重建过程的桶重映射偏差并保持输入顺序无关。 - 表 / 索引 DDL 进 WAL,删表不重取已移除句柄;库建删不进 WAL,删除以墓碑目录收敛。 -- 页内 compact 保持槽号及索引位置,死空间达到四分之一时自动整理;无隐藏列逐页整理,有隐藏列整表重写,不跨页填空以保留行序。 +- 自动页内 compact 保持槽号及索引位置,死空间达到四分之一时触发;显式 compact 经 WAL 按原扫描顺序打包存活行,回收跨页空洞和隐藏列字节,并重建索引位置。 ## 身份、权限与引导 + +### 对象编号 + - 对象标识使用数据库编号与库内表编号组合;数据库编号从 system catalog 的对象高水位分配,表编号从本库高水位分配,删除不降低计数器。对象解析只读取 catalog。 - 建表编号在 WAL 组写入前分配,随建表记录提交;目录应用时推进高水位,恢复使用日志编号。只有建表组复制操作列表,普通数据提交沿用借用列表。 + +### 身份与角色 + - 用户是可登录角色,共用名称空间;identities 保存属性、时间、稳定编号及版本,users 只存编号和口令哈希,编号不复用。 - 最高权限按身份属性判断,不按名称、不继承;默认用户 LOGIN、角色 NOLOGIN,两者 NOSUPERUSER / ENABLED。保护最后一个启用的登录管理员。 - 仅旧格式迁移按管理员参数识别初始最高权限;旧账号保留信息,角色补编号,重名拒绝;身份、凭据及删除清理用同一 Accounts WAL。 - server 判定权限,目录封装于 Server.Catalog;角色成员取向上闭包,写入拒绝环。GRANT role TO member 表示 member 继承 role 权限。 + +### 对象授权与会话失效 + - members 保持身份成员目录;对象授权存于受保护 __system_object_acl,使用稳定对象与身份编号,保存所有者、授予者和 grant option。CONNECT / CREATE 限数据库,四项数据权限限表或单库表范围;ALL 按作用域展开。 - PUBLIC 默认只提供业务数据库 CONNECT,可逐库撤销;CREATE 建表登记创建者所有权,数据库所有权不隐含他人表的数据权限。启用角色可继承所有权,不继承 SUPERUSER。 - 授权链从独立管理来源及所有权展开固定点;撤销清理无来源下游,保留独立来源,循环不能自持。禁用保留所有权和管理来源授权,停止权限贡献并清理失效下游。 @@ -69,45 +145,115 @@ - 权限快照按字符分块存储,比较旧快照后以同一 WAL 组替换;跨页及 Unicode 不受单行上限限制。普通存储入口隐藏并拒绝访问权限快照表。 - 服务端共享公平读写锁排序查询与权限变更;事务提交复查身份、权限和稳定对象。建表前写入创建者声明,启动时依据现存对象恢复所有权或清理未完成声明。 - 口令 / 属性推进 revision,权限变更预先展开受影响身份;TCP 只标记连接失效,下一请求回 unauthorized 后关闭,避免 Windows 阻塞句柄异步中断;登记在 finally 清理。 + +### 系统目录与引导 + - 系统表统一 __system_ 前缀并分层保护,内部目录按白名单访问;旧名按文件先、catalog 后迁移,崩溃后可重复收敛。 - 安装先 bootstrap:建立 system、默认 root(LOGIN / SUPERUSER / ENABLED)、18 个内置名称,再起服务;引导请求不开放 TCP。 - 清单编入引导并与解析器测试比对;system.__system_types 保存名称、基础表示、参数能力、编号。重复引导保留口令并补齐类型,冲突或身份降权失败;类型建表与写入用同组 WAL。 +### 本机 sudo 认证 + - sudo 认证用独立 allow_sudo_auth 属性和显式 sudo_auth_user 映射;默认关闭,只有 SUPERUSER 能管理,不继承、不隐含权限。目录管理者不得管理启用该属性的身份。 - 选择操作系统保护的随机本机凭据与 TCP 一次性 HMAC 挑战,以复用三平台既有会话协议;Unix 只信任有效 UID 0,Windows 只信任提升 Administrators 令牌。双方校验内核回环地址,不接受客户端自报 OS 用户或 SUDO_USER。 - 本机凭据只存放于系统保护的端口专属目录,原生入口校验提升身份;实例重启重新生成,现存目录拒绝覆盖。此方案要求服务端也提升运行,以保证创建凭据时的操作系统保护边界。 - 挑战绑定账号、连接及实例,60 秒过期并在每次尝试时消费;证明常量时间比对,凭据不经网络发送。成功登录复用身份版本、登录时间及连接失效机制,审计不含凭据或证明。 - sudo 属性由 Accounts WAL 持久化,旧目录缺列触发身份快照重写,旧记录缺属性默认 false,已有的错误类型明确拒绝。 +## 范式分析 + +- 范式检查采用阿姆斯特朗属性闭包与子集枚举,候选键声明转为决定全关系的依赖;完整覆盖声明与领域原子性分别控制可证明结论,不从样本推断。二元 BCNF 建议按违反依赖无损拆分,投影依赖之并用于验证依赖保持。 + ## 自定义类型 - - 范式检查采用阿姆斯特朗属性闭包与子集枚举,候选键声明转为决定全关系的依赖;完整覆盖声明与领域原子性分别控制可证明结论,不从样本推断。二元 BCNF 建议按违反依赖无损拆分,投影依赖之并用于验证依赖保持。 -- DOMAIN 命名基础类型,列编码 domain(名称,基础类型) 保留引用,值及索引沿用底层语义。 + +### DOMAIN 定义与变更 + +- DOMAIN 命名基础类型,列编码 domain(名称,基础类型) 保留引用,值及索引沿用底层语义。领域目录的 base 列保存类型、可空性与默认值,check_名称 列保存具名条件,旧的仅基础类型定义继续可读;未改变值、页或 WAL 编码版本。 +- DOMAIN CHECK 在独立 VALUE 槽位绑定,拒绝聚合及子查询,TRUE / UNKNOWN 通过。领域继承全部 CHECK 和非空限制,默认值按列、最近领域、基础领域选取;继承属性只在绑定时合成,不写回列声明。 +- ALTER DOMAIN 在库读门内取完整定义及数据快照,引擎校验传递依赖、默认值和已有行;库身份与 WAL 检查点组成精确令牌,在写门内复查后走 ReplaceSchema WAL。 + + 并发提交返回 serialization_failure;复用已有恢复与结构版本,不引入通用结构事务。创建依赖领域的表 / 领域也在发布点验证结构守卫;事务提交复查修改表及传递领域依赖。 - 各库 __system_domain_<名称> 空目录表的 base 列保存定义,复用 catalog / DDL WAL;普通 SQL 隐藏并保护目录。 - 嵌套只引用当前库已有类型,语义层从 schema 递归解析并拒绝循环,存储写锁内逐层校验;删除检查类型间及间接列依赖。 -- 类型 DDL 要求管理员、事务内禁止;约束与默认值后续扩展,暂不引入自定义函数 / 运算符。 +- 类型 DDL 要求管理员,事务内禁止。DOMAIN 已支持默认值、非空与 CHECK 约束;暂不引入自定义函数 / 运算符。 + +### 运行时类型与表达式 + - 运行时类型使用稳定构造器编号与结构化 TypeId,逻辑类型与 PhysicalType 分离;递归值使用版本 1 标签编码,读取时校验类型、形状及载荷。 - TypedExpression / TypedPlan 仅使用 schema 绑定,SQL BoundQuery 通过既有 RelOp 执行并按输出位置验证;输出类型保留嵌套 DOMAIN 名称,基础日期、时间戳及 Blob 保留兼容类型,函数结果不继承参数领域。 -- TypedExpression 列引用保存输入 schema 槽位与诊断名称;独立求值要求行顺序匹配,TypedPlan 扫描边界校验并按 schema 排序,每层投影绑定到子计划输出。SQL RelOp 在优化后绑定表达式列槽位,投影单向转为 Compute,排序/分组转为 BoundSort/BoundAggregate,存储结果按算子布局排列;子查询局部列在前、外层绑定在后。绑定算子不参与后续投影下推;独立作用域身份仍待迁移。 +- TypedExpression 列引用保存输入 schema 槽位与诊断名称;独立求值要求行顺序匹配,TypedPlan 扫描边界校验并按 schema 排序,每层投影绑定到子计划输出。 + + SQL RelOp 在优化后绑定表达式列槽位,投影单向转为 Compute,排序/分组转为 BoundSort/BoundAggregate,存储结果按算子布局排列;子查询局部列在前、外层绑定在后。 + + 绑定算子不参与后续投影下推;独立作用域身份仍待迁移。 - SQL 局部引用使用 ColumnSlot,外层引用使用 OuterColumnSlot 的相对位置及局部布局宽度。重新绑定外层引用只查询外层布局,避免同名局部捕获;语义输入拒绝执行槽位。外层行仍扁平化,多级词法作用域/来源编号另行迁移。 -- BoundQuery 执行前重新取得 schema 并比较依赖对象身份、schema 版本及列定义,依赖覆盖全部嵌套子查询及来源列的传递 DOMAIN 定义。IPC 将依赖守卫限定在本次执行环境;扫描、分片、点查及范围读均在相关库读锁内复查全部依赖后读取,跨库读锁按库名排序,持有库引用防止删除。数据、统计和无关对象不参与比较;旧目录缺失版本时仍比较列定义,已知身份或版本丢失则拒绝。守卫响应必须明确确认,旧二进制忽略字段时拒绝;未实现守卫的后端明确报错,纯内存视图可直接执行。守卫不改变既有多请求查询的数据隔离语义。 -- 内建函数先解析为稳定 FunctionId 并验证签名,再执行;SQL NULL 保留三值语义。缺少能力字典的运行时类型拒绝比较、排序、分组、极值、索引及唯一键声明。 + +### 查询依赖的结构守卫 + +- BoundQuery 执行前重新取得 schema 并比较依赖对象身份、schema 版本及列定义,依赖覆盖全部嵌套子查询及来源列的传递 DOMAIN 定义。 + + IPC 将依赖守卫限定在本次执行环境;扫描、分片、点查及范围读均在相关库读锁内复查全部依赖后读取,跨库读锁按库名排序,持有库引用防止删除。数据、统计和无关对象不参与比较;旧目录缺失版本时仍比较列定义,已知身份或版本丢失则拒绝。 + + 守卫响应必须明确确认,旧二进制忽略字段时拒绝;未实现守卫的后端明确报错,纯内存视图可直接执行。守卫不改变既有多请求查询的数据隔离语义。 +- 内建函数先解析为稳定 FunctionId 并验证签名,再执行;SQL NULL 保留三值语义。运行时描述保存 Eq / Ord / Hash 能力,List、Maybe、Tuple 根据参数递归派生,DOMAIN 沿用基础类型。SQL 比较和量词按运算要求能力,GROUP BY / DISTINCT 同时要求 Eq 和 Hash。 +- 复合值排序使用类型身份与结构的字典序;哈希按构造器与子值递归计算,统一浮点正负零,不依赖显示文本。类型和值编码仍为版本 1;哈希只用于内存执行,不需重建持久化索引。SQL NULL 与 Maybe Nothing 分开,空容器也保留完整身份。 +- 复合值的 Eq / Ord / Hash 不等于索引键能力;运行时索引及 UNIQUE / PRIMARY KEY 继续拒绝,索引连接仅对现有整数或文本键探测,其余走扫描 / 哈希回退。 - SQL 字面量生成返回明确错误,先验证运行时值与有限浮点;复合值在 Web 使用 SQL 修改。 ## 配置、构建与发行 + +### Web 编辑与受限管理 + - Web 编辑在首个业务表加载时建立快照,在提交 / 回退时结束;既有大库基准 BEGIN 269.806 ms、COMMIT 376.345 ms,不按每次单元格编辑重建整库快照。 - Web 登录分别建立普通 API / SQL 和编辑连接,页面 / 数据库标识绑定编辑事务,SQL 事务另绑定查询标签;同 Cookie 请求串行执行。 - 编辑集保留在浏览器,提交从固定保存点重放;失败回退整个编辑集,冲突回滚并重新加载,成功回执去重;系统身份修改不进入数据事务。 - system_catalog_manager 只管理普通身份,不继承、不隐含业务访问权限;存储写锁内再次拒绝特权目标及特权属性修改。 + +### 离线维护与配置 + - bootstrap 维护使用独占数据目录锁,在副本中修复并验证后保留原目录备份再发布;repair 不重放 WAL、不补初始化数据,原有数据文件必须字节一致。 - listen_host 是监听配置,static 固定为静态目录,管理员名由 --user 指定;data_dir 存数据,log_files 存日志,相对路径以启动目录解释。 -- resources/chusql.toml 入库并打包,UI 设置样本不入库、不进包,运行时按 resources、上一级 resources、工作目录候选查找。 +- resources/settings.toml.linux 与 resources/settings.toml.windows 入库并打包,安装时填入平台路径并生成 settings.toml;UI 设置样本不入库、不进包。配置路径以 docs/config.md 为准。 + +### 安装与门禁 + - 预编译包优先,server / 存储必装,Web / CLI 可选;Windows zip、Linux/macOS tar.gz。包内模板也放 resources/,按确切产物名打包并拒绝未知工件。 - 本地解包安装不联网,管理员名同时传 bootstrap 和 server;安装冒烟隔离配置并恢复用户 PATH,卸载可保留数据 / 配置。 - 门禁先刷新 release cdylib,再并行 Rust、串行 Haskell、注释三条车道;Server / Web 先刷新各工程的本地依赖,任一步失败即失败。 - 局部改动只测试受影响模块;较大改动由 agent 执行全量门禁。日志 / 临时文件在 logs/,必要时 -Full;门禁及打包强制 UTF-8 以避免 GBK 编码失败。 + +### 口令输入与诊断 + - CLI 终端隐藏口令,管道兼容 LF / CRLF / 无行尾,保留空格与内部回车,提示写 stderr。 - CLI 禁用逐行自动历史,只记录完整 SQL 与元命令;含 IDENTIFIED / PASSWORD(忽略大小写)的输入整体排除,避免多行口令或执行失败留下片段。解析错误也隐藏此类原文,筛选保守包含字符串和标识符中的同名文本,已有历史不自动删除。 - TCP 与 Web 使用同一解析诊断脱敏路径;Web 回归校验整个 HTTP 错误响应不含口令。内置 SQL 控制台记录结果或诊断,不将 SQL 原文写入日志,外部代理和采集需自行配置。 + +### 对象及结构版本编码 + - BoundQuery 保存来源对象身份及列定义;DOMAIN 依赖从来源列递归展开,执行前复查。库 / 对象编号在 TableInfo 中输出十进制字符串,读取兼容旧数值,零对象编号表示无有效身份。 -- 表级 schema_version 由 catalog 持久化,新表从 1 开始,旧目录缺失版本保留 0;结构变化递增,新增结构 WAL 记录保存确定目标版本,恢复不重新分配。线上使用精确十进制字符串并兼容数值输入,0 或缺失表示未知版本;IPC schema / 快照与内存 Server 保留版本,内存 DDL 同样递增并拒绝耗尽。 +- 表级 schema_version 由 catalog 持久化,新表从 1 开始,旧目录缺失版本保留 0;结构变化递增,新增结构 WAL 记录保存确定目标版本,恢复不重新分配。 + + 线上使用精确十进制字符串并兼容数值输入,0 或缺失表示未知版本;IPC schema / 快照与内存 Server 保留版本,内存 DDL 同样递增并拒绝耗尽。 - 注释以 AGENTS.md 为准;原因写本文件,限制写 known-issues.txt,进度及计数只以 progress.txt 为准。 + +### 容器部署 + +- 同一运行镜像包含数据库、引导、CLI 和 Web,Compose 将数据库与 Web 分为单进程服务;Web 不挂载数据库目录。运行 UID/GID 为 10001,命名卷保存数据、日志及编辑器偏好。 +- 每次 server 启动复用既有幂等 bootstrap,口令从文件经 stdin 输入,不使用文件标记判断系统目录状态;失败阻止启动,不自动 repair / reset。已有口令不随 secret 文件修改而重设。 +- Rust 与 Haskell 使用固定 digest 的 Bookworm 构建阶段,运行层沿用 Bookworm。BASE_REGISTRY 只替换下载地址,保持 digest 校验;Debian 与 Cargo 镜像源保留签名及锁文件校验。源码构建单任务且限制 GHC 堆,WSL 使用 1 核 / 3 GiB、无额外交换空间的 Buildx 或异机构建导入。 +- Compose 通过 CHUSQL_IMAGE 固定验收镜像,服务默认限制 1 核 / 512 MiB、128 个进程或线程且无额外交换空间。不同 UID 的旧数据卷须停机备份后显式调整所有者,不由服务启动脚本自动递归改权限。 + +## 博客业务接入 + +- 业务用户与数据库身份分离,角色使用标量 CHECK;账号完整 Argon2id PHC、发布授权、文章权威状态、评论、互动、审计及迁移标记持久化,可重建文章索引独立。正文与资源留在 Git 文件,接入验收见 docs/blog-database.md。 +- 标量索引键上限为 min(128, floor((page_size - 11) / (order - 1)) - 12),保留按旧 64 字节预算校验配置的规则,避免现有合法页 / 分支数组合失效。旧索引头可读取,首次写长键更新能力字段;页、槽位、WAL 与键排序编码不变,提交前及堆直接写入共用配置上限。 + +## 存储并发与页恢复 + +- 全局公平门排序权限和 DDL;SQL 数据准备共享库门,最终约束校验与 WAL 发布串行,以保留连续已应用提交前缀。行锁等待位于库门外,持有内部行编号及旧、新唯一值锁;固定名称顺序用于跨库门,等待图用于跨请求行锁。环中的新等待者中止,锁等待总上限 5 秒。保存点回滚恢复计划和读依赖,严格持锁到事务结束。 +- 行版本保存在独立的 mvcc.json,以 WAL 提交 LSN 为可见序号,使用不复用内部行编号、起止序号、内容版本和逻辑行序。内容版本与位置变化分开,避免其他行的删除或排序造成伪写冲突。发布顺序是逻辑 WAL、数据与索引、版本目录、库检查点;重放后幂等发布版本。版本超前于可恢复 WAL 时拒绝打开,不冒充已完成恢复。 +- 选择独立版本文件以保留现有页与键格式,代价是整库扫描和版本文件写放大。SQL 仍使用物化工作行集;默认快照隔离,SERIALIZABLE 写事务按表保守复查读依赖。版本保留到最老活跃快照,结束事务回收内存,后续发布回收磁盘版本。database_snapshot 的单版本缓存继续供普通后端读取,不承担事务存活登记。 +- 保留现有页内布局,以 .page-wal 记录 CPW1 全页镜像、写序号与校验和,以版本 1 的 .pages 保存页 LSN。镜像先同步,数据文件再同步,页元数据经临时文件原子替换并同步目录,最后清理镜像;库 WAL 检查点在这些步骤之后推进。 +- 同一逻辑提交可多次刷新同一页,镜像按独立写序号恢复,不仅按页 LSN 比较;截断也写入重置标记。缓存淘汰先记录并写回当前脏页批次,避免反复记录未修改的缓存页。日志错误使当前页句柄进入恢复封闭,保留材料而不靠析构重试。 +- 已提交逻辑组重放前丢弃受影响表的派生索引,再依据修复后的堆重建;整表载荷直接重写,避免残缺根或部分行集阻断幂等恢复。账号变更统一走带提交标记和检查点的组,保留旧账号日志解码 / 恢复。 +- 显式 compact 在独立文件代次复制堆与索引,最终库写门内追平并发变更,保留切换时逻辑行序。影子文件同步后用 Migrate WAL 发布 catalog.file_generation,对象身份与结构版本不变。旧快照阻止退役文件删除;启动恢复后清理孤立代次。保留有序前缀、重写其余后缀避免重排可观察行序,代价是变化较多时切换窗口变长。启动隐藏列整理保留离线 Compact 日志兼容。 diff --git a/.agents/context/known-issues.txt b/.agents/context/known-issues.txt index e3c9a9d..6082cbc 100644 --- a/.agents/context/known-issues.txt +++ b/.agents/context/known-issues.txt @@ -2,29 +2,60 @@ 进度见 progress.txt,设计见 design-decisions.txt;仅记录未解决的限制。 ## 事务、恢复与并发 -- 事务是整库内存快照,不是行版本 MVCC;每会话一个事务,无嵌套事务,事务内禁止 DDL / USE。 -- BEGIN / COMMIT 仍有整库快照传输与修改表比较成本,复测见 docs/performance.md。 + +### 事务快照与冲突 + +- SQL 工作行集仍整库物化,持久化行版本目录每次发布也会读取整库并写出文件。每会话一个事务,无嵌套事务,事务内禁止 DDL / USE;未提供按需版本读取和增量版本日志。 +- BEGIN / COMMIT 仍有快照传输和修改表比较成本。SERIALIZABLE 写事务按表复查读依赖,可能因不同行的变化发生保守冲突;未提供谓词锁或 SSI。长期快照阻止旧版本和退役文件回收,增加内存、磁盘与 I/O 成本。旧版本的内存回收随事务结束完成,磁盘版本文件在后续发布时收缩。 + +### Web 编辑生命周期 + - Web 首次加载业务表即固定编辑快照,同一登录会话只允许一个页面持有编辑事务;系统身份表只读,通过 SQL 管理。 - 页面关闭的回滚请求可能因断线未送达;此时按会话空闲 / 最长寿命过期清理,后台每分钟检查一次。编辑连接失效后必须重新登录,不能恢复旧快照。 -- COMMIT 按整数 id 校验写写冲突,缺少整数 id 时整表比对及替换;冲突返回 serialization_failure,调用方回滚或重试,无自动重试或死锁检测。 -- WAL 只有 redo,检查点按库 LSN 而非页 LSN,幂等恢复代价随数据量增长;库目录建删不走 WAL,删库用墓碑目录处理。 + +### 提交与存储边界 + +- 行锁和唯一键锁跨请求保留到事务结束,保存点回滚不提前释放锁。总锁等待上限为 5 秒,死锁或超时中止事务;调用方须 ROLLBACK 后重做业务检查,无自动重试。缺少可用整数 id 或旧重复 id 时,物理提交可能整表替换,但合并与冲突使用内部行编号。 +- 原始存储整表替换仍兼容旧重复 id;普通插入会在提交前拒绝 id 索引冲突。这不表示存储端已完整执行 SQL 的全部唯一性和类型约束,SQL 约束仍由引擎校验。 + +### 恢复与锁 + +- 逻辑 WAL 仍为 redo,逻辑重放范围按库检查点决定。页 LSN 与全页镜像用于修复撕裂页,不代表已经实现按页跳过任意逻辑操作;恢复需重建受影响表的派生索引,代价随数据量增长。库目录建删不走 WAL,删库用墓碑目录处理。 - recovery_required 期间除 Ping / SystemStatus 外请求被拒绝,需恢复后继续。 -- 每库读共享、写独占,写入会阻塞同库跨表读取,尚无并行写。 +- 同库可并行准备不同行的修改;最终校验、WAL 发布和页刷盘仍按库串行。权限和 DDL 全局排序。管理员原始存储写入不取得 SQL 事务行锁,版本变化会使冲突的旧事务拒绝提交。未给出吞吐量或尾延迟保证。 - 权限变更只标记 TCP 连接失效,客户端下一次请求收到 unauthorized 后关闭,空闲连接不会立即断开;并发测试不证明性能提升。 ## 查询与性能 + +### 行与索引容量 + +- 堆行的 JSON 编码必须放入单页(默认 4096 字节,含页头与槽位开销),尚无长行溢出页;TEXT 不表示可存任意长度正文。普通提交组会在写 WAL 前拒绝超页行。 +- 标量索引键默认最多 128 字节,按页容量与分支数计算有效上限,密集旧配置可能仍只有 64 字节;字符串按 UTF-8 字节计数,普通写入与建索引在提交前拒绝超限。非索引文本仅受声明长度和整行容量限制;写入长键后不得降级到仅支持 64 字节的旧二进制。 + +### 成本估算与统计 + - 基础成本及贪心连接重排,无动态规划或跨外连接重排;只在行序不可观察处重排。 - catalog 行数可能滞后,distinct 有上限;16 桶等宽直方图只统计数值并按闭区间估算,增量维护可能偏差,桶内分布仍为估算。 - 内存统计去重上限为 4096,暂不提供直方图或索引成本;派生表可从透明算子估计行数,含聚合或可能报错表达式时仍保守。投影下推保留所有计算项,不消除潜在错误。 + +### 子查询与并行执行 + - 查询内物化只在内存保存结果,尚无容量预算或磁盘溢出;既有按绑定分组求值可能更早报告同一错误。 - CTE 解析期展开,不支持递归、写语句或 MATERIALIZED / NOT MATERIALIZED 指定;不同优化子树不能共享物化。只能引用前面定义的 CTE,前向引用按普通表名解析。 - 半连接重写尚未覆盖组合谓词、复杂相关条件、多键、相关聚合或排序截断;可能报错的相关投影继续走原执行路径。 - 并行只覆盖页区间扫描:schema 至少 1000 行、最多 8 线程,无页内并行,统计滞后可退回顺序扫描。 -- compact 不填跨页空洞,含隐藏列时仍需整表重写。 +- 显式 compact 使用影子文件在线复制和 WAL 代次切换,但仍物化完整行集。最终追平与切换独占库门;并发变化较多时可能重写较长后缀,不能保证固定切换时延。中途失败的未发布代次在重启恢复后清理;启动隐藏列整理仍离线重写。 ## 权限与兼容性 + +### 旧数据与对象身份 + +- 旧目录或历史行中的非法字段名不自动改名;原始扫描与旧 WAL 重放仍可用,但新写入或重写载荷须提供合法顶层字段名。迁移需显式整理字段,不能靠升级自动修正。 - 对象权限快照整体写入,鉴权会读取身份、成员和对象元数据;尚未针对大规模权限目录做性能基准。 - 对象高水位损坏或回退后无法恢复已删除对象的编号上限;旧二进制会丢弃新增目录字段,不应降级使用已升级的数据目录。 + +### 权限功能与迁移 + - 无列级权限、所有权转移或角色 ADMIN OPTION。 - 旧授权缺少授予来源,迁移为管理来源;旧全局 * 只绑定迁移时现存表。没有身份改名命令;已有同名 public 身份在删除前不会解析为虚拟 PUBLIC。 - 尚无 CREATEDB / CREATEROLE、继承开关、口令到期、连接上限或 Web 专门的身份属性编辑界面。 @@ -33,24 +64,58 @@ - 引导不重设已有口令、不提升已降权身份;类型定义冲突需人工解决。 ## 类型与语义 + +### 范式与类型能力 + - 范式分析最多 12 列;领域原子性和依赖完整性由用户声明,信息不足时不认证高阶范式。分解建议仅一轮,不保证子关系已达 BCNF;尚无自动迁移。 -- DOMAIN 无自身 CHECK / NOT NULL / DEFAULT、ALTER DOMAIN、CASCADE;尚无 ENUM 或用户定义复合类型。内置目录不能靠增加行扩展基础类型。 +- DOMAIN 尚无 CASCADE、改名、修改基础类型、NOT VALID 及显式事务内 DDL;ALTER DOMAIN 读取整库快照,尚无按依赖扫描或磁盘溢出;尚无 ENUM 或用户定义复合类型。内置目录不能靠增加行扩展基础类型。 - DECIMAL 仍使用浮点表示,不是精确十进制存储;整数类型共用整数表示,CHAR 不补空格。 - 少量接口设置仍用字符串类型名;Haskell 值语义和 Rust 索引键分开维护。旧 ColumnType / RelOp 仍是兼容桥,完整能力、转换及关系 IR 迁移待后续阶段。 + +### 绑定与执行隔离 + - 多请求查询不提供整条查询的数据快照;旧目录无有效对象编号时无法证明历史对象身份。执行期外层行仍使用扁平布局,原始关系执行 API 仍允许名称引用;尚无独立作用域或来源编号。 -- 写入的存储操作分别取门,尚无整条语句的数据快照或数据冲突检测。来源/列缺少独立身份,不能视作完整写入 bound IR;建表、库及 DOMAIN 管理不在已有表写计划范围。 +- 引擎直接调用存储时,各次操作分别取门,尚无整条语句的数据快照或数据冲突检测。服务端会话已对数据写入及提交整体串行,但不提供自动提交语句在 I/O 失败后的整体回滚。来源/列缺少独立身份,不能视作完整写入 bound IR;建表、库及 DOMAIN 管理不在已有表写计划范围。 - CHECK 仍以表达式文本持久化;RENAME COLUMN 不自动改写依赖 CHECK,引用旧列名时拒绝改名。普通原始存储 DDL 不具有 Haskell 的完整表达式语义校验。 -- 运行时类型尚无 Eq / Ord / Hash 等 capability 字典,不提供比较、排序、分组、极值、去重和索引;复合字段在 Web 通过 SQL 修改,没有结构化单元格编辑器。 + +### 复合值与协议 + +- 内建运行时类型已提供 Eq / Ord / Hash 能力,尚无用户注册的运算实现或复合索引键编码;运行时类型的索引、UNIQUE / PRIMARY KEY 仍拒绝。复合字段在 Web 通过 SQL 修改,没有结构化单元格编辑器。 - 运行时协议使用版本 1,旧客户端不支持新增类型化值;Web 的 JSON 数值仍受 JavaScript 安全整数范围限制。 - 派生表输出取裸列名,重复名称报错;未定型 NULL 仅用于查询类型推导,不可声明为存储列类型。 ## 构建、发行与安全 + +### 离线维护 + - 离线 recover 依赖完整可用 WAL,不能保证修复损坏数据页或已截断的历史;未知系统表缺少结构时需备份或 reset。目录计数器损坏后无法还原已删除身份编号上限。 - 旧版进程不支持数据目录独占锁;维护前必须停止所有相关进程。 + +### 本机认证与平台验收 + - sudo 本机认证需提升身份启动 server;当前只映射 Unix root / Windows 提升 Administrators 到一个显式配置身份,无任意 OS 用户映射或自动提权。异常退出留下的端口凭据目录须在确认停止后手工清理。 - sudo 的 Windows 提升成功路径、macOS 编译运行及 Linux 完整提升 server/CLI 链路仍待目标平台实机验收;Debian/WSL 已验证原生凭据安全边界。 + +### 构建与发行 + - 直接构建独立 Stack 工程时可能复用旧注册库,必要时使用 --force-dirty 或全量门禁 -Full;Haskell 构建须串行。 - 存储协议变化后必须重建实际 cdylib,开发环境须配置 PATH / LD_LIBRARY_PATH;旧命名构建工件仍可能残留。 - 真实 server 测试须先引导并能找到 bootstrap;注释检查对部分多行语法可能误报。 - GitHub 在线安装、Linux $ORIGIN 与 macOS 发布仍需实机验证;无 Release 时在线安装无法取得预编译资源。 - SHA256 只能检测损坏,无发布签名;外部采集仍可能记录 SQL 原文。旧 CLI 历史不自动清理,任意业务字符串中的敏感数据不自动识别。 + +### 容器验收范围 + +- 容器仅验收 Linux amd64、本次工作区源码镜像及本机已有 ChuBlog 数据库镜像的升级;五分钟负载与 SIGKILL / 检查点 ENOSPC 回归不替代生产长期稳定性、真实断电或任意版本升级验证。 +- 部分 Docker 代理的镜像源模式会返回 502,可显式设置 BASE_REGISTRY;构建器不自动继承 Engine 的镜像源。WSL 曾退出但原因未确认,仍须限额构建,或在构建机生成后导入。 + +## 博客接入边界 + +- examples/blog 提供数据库 schema、旧文件字段映射及真实驱动验收,不修改 ChuBlog 当前文件账户实现。生产账户迁移、HTTP / SSH 授权、会话与查阅凭据版本检查、哈希升级、限流、匿名身份合并及文件访问控制仍由 ChuBlog 配套实现。数据库或身份查询失败时应用必须拒绝受保护访问。 +- 博客关联尚无数据库外键;双方写入及物理删除需采用 SERIALIZABLE 事务检查存在性和关联明细。评论按字数、UTF-8 字节、请求体和配额限制,整行仍须适配页容量,不提供长行 / 溢出存储。 +- 本阶段没有重建 Docker 镜像;已验收镜像仍对应 progress.txt 中的可靠性阶段版本,不含当前事务及长键改动。腾讯云内网 Debian 源仅按要求修改,未执行网络或构建验证。 + +### 页格式与升级边界 + +- 新增 .pages(版本 1 页 LSN / 写序号)、.page-wal(CPW1 全页镜像)及临时 .pages.pending。停机备份和迁移必须复制整个数据目录,不得只复制 .db / .idx;首次写入页版本后禁止旧二进制写该目录。 +- 全页镜像可修复镜像已完整同步后的撕裂写;可检测到的镜像或页元数据格式损坏会报错,不能检测或修复任意介质损坏。不提供真实断电、文件系统或硬件缓存丢失的保证。 diff --git a/.agents/context/main-roadmap.txt b/.agents/context/main-roadmap.txt index 70cfe46..c96ce70 100644 --- a/.agents/context/main-roadmap.txt +++ b/.agents/context/main-roadmap.txt @@ -1,20 +1,29 @@ -ChuSQL 长期路线图 +# ChuSQL 长期路线图 交付状态和验收只以 progress.txt 为准;近期顺序见 side-branch-plan.txt。 本文件描述目标,不代表现有实现或功能承诺。 -目标链路:SQL → Parser / Binder → Typed IR → Planner / Optimizer → Executor → Rust Storage。 +目标链路:SQL → 解析与绑定 → 类型化中间表示 → 规划与优化 → 执行 → Rust 存储。 + +类型化中间表示(Typed IR)是已经确定类型与引用关系的查询结构;能力(Capability)描述类型支持的运算。代数数据类型(ADT)用于表达多个可选构造分支,多版本并发控制(MVCC)用于管理数据版本和读取快照。 + 类型能力与权限保持独立;catalog 保存对象、依赖和语义,内核保留必要基础机制。 -阶段 -- A 类型与函数基础:稳定 TypeId / FunctionId、注册表、逻辑/物理类型分离、版本化值;验收见 progress.txt。 -- B 能力与运算(2–6):Capability、Operator、Cast、Aggregate、参数多态与约束解析。 -- C 复合与自定义类型(7–12):ADT、Record/Composite、Newtype/Domain、参数化类型、Range、用户类型。 -- D 函数与效果(13–16):用户函数、Effect、纯 Generated Column、有副作用的 Trigger。 -- E 权限与类型化查询(17–19):权限 Capability、Query a、Rewrite / Optimizer 函数化。 -- F 扩展:对象体系统一后实现 Extension 的版本、依赖、安装/升级/移除;其他访问方法按真实需求推进。 +## 阶段目标 + +按以下阶段推进;括号中的编号沿用原路线图: + +| 阶段 | 目标 | +| --- | --- | +| A 类型与函数基础 | 稳定 TypeId / FunctionId、注册表、逻辑/物理类型分离、版本化值;验收见 progress.txt。 | +| B 能力与运算(2–6) | 类型能力、运算符、类型转换、聚合,以及参数多态与约束解析。 | +| C 复合与自定义类型(7–12) | 代数数据类型、记录/复合类型、命名类型/领域、参数化类型、范围和用户类型。 | +| D 函数与效果(13–16) | 用户函数、效果管理、纯计算生成列和有副作用的触发器。 | +| E 权限与类型化查询(17–19) | 权限能力、类型化查询 Query a,以及查询重写与优化器的函数化。 | +| F 扩展 | 对象体系统一后实现 Extension 的版本、依赖、安装/升级/移除;其他访问方法按真实需求推进。 | + +## 贯穿约束 -贯穿约束 - 现有 ColumnType / Expr / RelOp 有真实消费者;迁移时逐步收拢,不提前删除兼容桥。 - 每阶段验证持久化、升级、依赖和恢复,不能靠重新初始化掩盖不兼容。 - 内建对象可由可信 bootstrap 元数据恢复;用户对象依赖 WAL / 备份。 diff --git a/.agents/context/progress.txt b/.agents/context/progress.txt index 5ac01d6..f0db259 100644 --- a/.agents/context/progress.txt +++ b/.agents/context/progress.txt @@ -1,9 +1,11 @@ -ChuSQL 已完成事项 -更新:2026-10-13 +# ChuSQL 已完成事项 +更新:2026-10-16 本文件是当前完成状态及最新验收的唯一来源,等价于 project-plan.txt;不保留历史批次、提交记录或修改流水。 设计见 design-decisions.txt,未解决限制见 known-issues.txt,后续计划见 side-branch-plan.txt。 +近期第一阶段“数据库可靠性与部署验收”、第二阶段“博客业务持久化与驱动联调”及第三阶段“存储并发与恢复扩展”已完成数据库侧本地验收。第三阶段包括持久化行版本、行与唯一键锁、死锁与锁等待取消、同库并行数据准备、在线文件代次迁移,以及页 LSN / 全页镜像恢复。整库物化、串行最终提交和切换窗口的成本见 known-issues.txt。ChuBlog 实际业务接入、生产文件迁移、长期运行及真实断电仍保留配套边界。 + ## SQL 与查询执行 - 实现 CRUD、表列约束、索引、INNER / LEFT JOIN、聚合、GROUP BY、HAVING、ORDER BY、LIMIT、投影别名、DISTINCT / ALL;排序支持输出序号、表达式、函数、聚合及子查询。 @@ -12,30 +14,116 @@ ChuSQL 已完成事项 ## 类型与绑定 +### 类型表示与 DOMAIN + - 建立固定类型 / 函数编号、TypeId / TypeExpr / Kind、逻辑与物理类型、版本化复合值编码;支持 Int / Double / Bool / String / List / Maybe / Tuple、length / not,接入 SQL、存储、CLI 和 Web。 -- 实现 CREATE / DROP / SHOW DOMAIN、库内嵌套定义、列引用、依赖与循环校验及持久化;查询输出保留 DOMAIN 身份。 +- 内建类型描述提供 Eq / Ord / Hash 能力,List / Maybe / Tuple 根据参数递归派生,DOMAIN 沿用基础能力。复合值支持结构比较、排序、JOIN、IN / ANY / ALL、分组、去重及 MIN / MAX;完整身份不隐式转换,保留 SQL NULL / Nothing、稳定排序及正负零的相等哈希一致性。索引与唯一键边界见 known-issues.txt。 +- 实现 CREATE / ALTER / DROP / SHOW DOMAIN、库内嵌套定义、列引用、依赖与循环校验及持久化;支持领域 DEFAULT / NOT NULL / 多条具名或匿名 CHECK、约束继承、默认值优先级与旧数据校验,查询输出保留 DOMAIN 身份。 + +### 查询与写入绑定 + - 查询使用 BoundQuery;表达式、投影、连接、排序和分组按 schema 槽位绑定,存储返回行按布局整理,缺列和位置失配明确失败。 - 相关列按最近到最远的独立词法作用域解析,局部 / 外层槽位分离;重绑定保留有效位置,失配仅允许唯一同名列重定位。子查询取值与缓存共享槽位绑定。 - DML 使用可复用 BoundWrite,预绑定 INSERT 输入、UPDATE 目标、DELETE 布局及 CHECK / 非空 / 唯一性约束;保留默认值、自增、逐项赋值和未命中行不求值,唯一性按最终行集判断,失败不发布修改。 + +### 依赖复查与约束发布 + - 查询与已有表写计划保存对象身份、schema 版本、列定义及传递 DOMAIN 依赖;执行前及实际存储操作锁内复查。写前握手拒绝不支持守卫的存储,跨库按名称排序取门;数据、统计和无关结构变化不使计划失效。 +- ALTER DOMAIN 校验一致整库快照,并在存储写门内复查库身份和提交点后通过既有结构 WAL 发布;并发提交返回 serialization_failure。依赖领域的建表及领域创建使用结构守卫,事务提交复查修改表及传递领域依赖。 - CHECK 定义与执行共用类型及槽位绑定;建表、加列和结构变更校验条件、默认值与键能力,空表不跳过,失效引用明确拒绝。 ## 存储与事务 +- SQL 查询与数据写语句使用存储事务;同库不同行可以并行准备,行锁等待不占库提交门。最终权限 / 对象 / 约束校验与 WAL 发布仍串行;权限与 DDL 全局独占。真实 TCP 验证不同行合并提交、旧快照读取、死锁返回和断线释放行锁。 + - 实现页、堆表、B+Tree、catalog、WAL、LSN 检查点、已提交组幂等恢复及页内 compact;持久化对象编号、高水位和 schema 版本,失败进入 recovery_required。 -- 实现按连接隔离工作库、整库快照事务、写写冲突检查、保存点和差分提交;权限及对象身份在事务提交时复查。 +- 实现按连接隔离工作库、持久化行版本快照、行级写写冲突检查、保存点和合并提交;权限及对象身份在事务提交时复查。COMMIT 在发布前复用引擎规则校验合并最终行集,拒绝不同整数主键形成的 UNIQUE 冲突,失败不发布其他表修改。 +- 支持 BEGIN [TRANSACTION] ISOLATION LEVEL SERIALIZABLE 及 START TRANSACTION ISOLATION LEVEL SERIALIZABLE,写事务提交按表复查全部读依赖的 schema 和数据,包含子查询和幻行;保存点回退恢复读依赖,只读快照可完成,默认 BEGIN 保留不同行合并行为。 + +### 提交前校验 + +- 普通 WAL 提交组在落盘前复用堆行与索引键编码检查行大小及有效索引键长度,覆盖单行 / 批量插入、整表替换、事务、结构替换及整理;超限输入不改变数据、索引、catalog、WAL 或检查点,不触发 recovery_required。 + + 建索引先校验已有值,结构替换按实际保留的索引校验;堆表直接写入与整表替换也在修改前拒绝超限键。 +- 新插入 id 的冲突在普通 WAL 提交前按操作顺序预检,覆盖单行、批量及跨表事务;复用实际键编码,按需点查并缓存键计数,支持先删除再插入及整表替换。保留 NULL / 缺失 id、旧重复 id 与重复删除键只删除首行一次的兼容行为。 +- 普通写入可能扩列时,在提交前按操作顺序复用 catalog 规则预演列推导和 schema 版本递增;结构替换及整理的载荷行参与预演。版本耗尽不发布数据或日志修改;同一行多列只递增一次,未定型 NULL 不扩列,版本上限不阻断无需结构变化的数据写入。 +- 存储协议的表名、列定义及写入行顶层字段名共用名称规则;单行、批量、整表替换、结构替换和事务载荷在处理请求时拒绝非法字段名。值内部键和文本不受字段名校验影响,旧数据扫描与已提交旧 WAL 重放保持兼容。 + +### Web 编辑事务 + - Web 编辑使用独立连接与页面绑定,支持跨表原子提交、保存点重放、提交去重、冲突重载、SQL 标签隔离及退出清理。 ## 身份、工具与发行 - 用户与角色统一名称空间,支持 LOGIN / SUPERUSER / ENABLED、稳定编号、角色继承、迁移及删除清理;权限变更使受影响会话失效。 - 实现对象所有权、grant option、DATABASE CONNECT / CREATE、表级数据权限及 PUBLIC、SHOW GRANTS、REVOKE GRANT OPTION FOR 和失效授权级联清理。 + +### 认证、工具与发行 + - 实现默认关闭的本机 sudo 身份映射、受保护凭据、回环校验与一次性 HMAC 挑战;已验证 Windows 非提升拒绝及 Debian/WSL root 凭据安全边界。 - 范式检查通过 Haskell / TCP / CLI / Web 提供只读分析,依据 schema 与声明检查 1NF / 2NF / 3NF / BCNF,输出违反依赖、一次无损分解及依赖保持结果。 - 引导初始化 system、默认 root 与 18 个内置类型,重复引导保留口令并拒绝冲突;实现 system_catalog_manager 及 bootstrap repair / recover / reset。 - 统一监听、数据 / 日志目录与配置模板;完成 Windows 分组件打包安装冒烟、管道口令兼容、敏感 SQL 诊断 / 历史脱敏及 UTF-8 构建。发行与平台未验收事项见 known-issues.txt。 +## 容器部署 + +- 提供多阶段 Dockerfile、默认数据库与可选 Web 的 Compose 配置、非 root 服务、文件口令、幂等引导、数据 / 日志 / Web 偏好卷、协议健康检查和停机备份说明。 +- 构建按单任务执行,GHC 构建堆上限 1536 MiB;运行服务各限制 1 核和 512 MiB,文档提供 3 GiB 上限的 Buildx 构建器及异机构建导入方式。 + ## 最新验证 -- 全量门禁通过:Rust 191 / Engine 598 / Server 163 / Web 80 / CLI 20 / Bootstrap 9,均零失败;动态库重建、Clippy、注释检查及 git diff --check 通过;受影响 HLint 仅保留既有惰性相关建议。 -- 验收入口:gate-check/run-gate.ps1;最新日志:logs/empty-in-gate.log。局部改动验证受影响模块,较大改动执行全量门禁;当前工作区改动未提交。 +### 门禁结果 + +- 全量门禁通过:Rust 221 / Engine 619 / Server 177 / Web 80 / CLI 20 / Bootstrap 9,均零失败;release 动态库重建、Clippy、注释检查及 git diff --check 通过。 + + 受影响 Haskell 源码与测试 HLint 无建议;Fourmolu 格式及幂等检查通过。 + +### 存储回归 + +- 回归验证超页行与超长索引键在提交前拒绝,失败后文件不变且可继续读写和重启;覆盖 UTF-8 字节边界、NULL、建索引失败与移除索引后的结构替换。真实 TCP 验证超限 SQL 写入后仍可查询与写入。 +- 重复 id 回归验证单行 / 批内 / 跨操作冲突均不改变持久文件,事务早先的跨表修改不发布;合法删除再插入可提交并重启点查。验证整值浮点等键、NULL / 缺失 id 及旧重复 id 的删除顺序;真实 TCP 验证重复 id SQL 插入报错后仍可查询和合法写入。 +- 扩列回归验证单行、批量、整表替换、结构替换及事务在 schema 版本耗尽前拒绝,失败后持久文件不变,原表可读、合法写入及重启正常;同一行多列与未定型 NULL 的版本行为保持一致。 +- 非法字段名回归覆盖六种写入路径,空名、路径字符、点号、空白、非 ASCII 字符和 NUL 均在写入前拒绝且文件不变;合法文本及嵌套对象可重启读取,旧式字段名的已提交日志仍可重放并继续合法写入。 +- 验收入口:gate-check/run-gate.ps1;最新日志:logs/mvcc-stage-gate-final.log,真实 TCP 日志:logs/id-preflight-tcp.log。当前工作区改动未提交。 + +### DOMAIN 回归 + +- DOMAIN 回归覆盖继承默认值、显式 NULL、UNKNOWN、非空、多条约束及命名、空表定义校验、加列 / 改类型、旧行与依赖默认值拒绝、绑定失效、真实 FFI 重启与并发插入冲突;Rust 验证发布失败不改持久文件、结构版本递增及已提交日志重复恢复,Server 验证管理员权限、事务 DDL 禁止和领域变更后的旧事务提交拒绝。 + +### 复合值运算回归 + +- 覆盖数字与前缀排序、可选值和元组顺序、嵌套 Eq / Ord / Hash 一致性、NULL / Nothing、空容器身份、非有限数拒绝、分组 / 去重 / 极值、连接 / 成员 / 相关存在与量词比较;真实 FFI 验证重启后的复合 DOMAIN、隐式 id 索引回退、修改和删除,Web 经 HTTP / TCP 验证结构值比较、排序和分组。值与类型编码保持版本 1。 + +### Docker 验证 + +- 完整多阶段源码镜像构建通过,Rust / Haskell / 运行阶段均为固定 digest 的 Bookworm 镜像;本地验收镜像为 chusql:local,ID / 仓库摘要为 sha256:4b22ced1f95c80c6904a5c794acac02d141b3e1dc91a619692c07dc020fcc720。构建器限制 1 核 / 3 GiB、无额外交换空间,GHC 堆上限 1536 MiB;构建完成后已停止构建器。 +- 默认与 Web profile 的 Compose 配置、TOML、脚本语法、入口与健康检查错误分支通过;独立 Compose 项目验证固定镜像、首次引导、非 root 卷权限、TCP / HTTP 健康检查、CLI、Web 登录、1 核 / 512 MiB / 128 进程限制及无额外交换空间。 +- docker/test-runtime.py 在真实源码镜像上完成 300 秒、三个会话并发负载:1696 次成功提交、2415 次明确冲突;SIGKILL 恢复后 1701 个关联事务完整,全部已确认提交保留,未提交数据丢弃。 +- 用容器内 16 MiB 临时文件系统制造检查点 ENOSPC,验证 WAL 已提交后的错误、业务请求封闭、日志保留、重启幂等重放及恢复后写入;不填满宿主磁盘。验证重复引导不覆盖原口令,停机备份恢复到空卷后业务行、账号和只读授权保留。 +- 本机已有 ChuBlog 镜像 sha256:afd2394af5606169b7dbf5b08f4e30fe0521fe47b0b6fbd7c53a67154388c354 的测试数据,在停机并将卷所有者从 10003 调整为 10001 后,可用本次镜像打开、保留原口令并继续写入;不据此承诺任意版本升级兼容。 +- ChuBlog 当前固定 Rust 驱动的 2 项单元测试与 4 项协议测试通过,覆盖错误码、断线、超时、取消及响应大小;真实 TCP 示例完成 Unicode / 布尔值 CRUD 与结果映射。博客业务数据库侧验收见下节;ChuBlog 生产文件迁移仍需配套实现。 +- 日志为 logs/docker-source-build.log、logs/docker-runtime-acceptance.log、logs/docker-integration-check.log、logs/docker-upgrade-check.log 和 logs/blog-driver-tests.log。全部测试容器、网络及测试卷已清理;本次未改动 ChuBlog 源码。 + +### 博客业务与驱动验收 + +- examples/blog/schema.sql 与 acceptance.rs 提供账户、完整 Argon2id PHC、角色 CHECK、发布路径 / SSH 公钥、文章权威状态、评论、互动、计数、审计及迁移标记的模型和实际 Rust 驱动验收;正文不入库,可重建索引独立。 +- 实际驱动验证旧 reader / publisher / admin 及禁用账号映射,完整 PHC 原样保存、参数与盐保留且可验证原口令;独立盐产生不同哈希,错误口令拒绝。迁移输入缺失授权时拒绝,同一来源重复迁移不重复写入。该验收使用构造的旧文件副本,不读取或迁移生产账户。 +- 验证不同主键并发注册仍只有一个用户名、跨表失败不部分发布、撤权后的旧读事务拒绝、文章删除与并发评论冲突、点赞 / 收藏并发计数、去重与重复取消、负数拒绝、匿名 / 登录评论关联、同时间游标分页、可见评论聚合 / 重算及超页评论拒绝后继续读写。 +- 验证文章查阅口令完整 PHC、撤销版本及管理审计持久化,文章索引重建不覆盖隐藏 / 删除 / 精华等权威状态;仅获文章索引表权限的数据库账号不能读口令哈希或改管理状态,关闭连接后的查询明确失败。HTTP / SSH / 文件访问授权仍由博客实现。 +- 标量索引键默认支持 128 字节,实际上限按页容量及分支数计算;真实驱动验证 113 字节文章键,Rust 回归覆盖 128 字节键跨页 / 重启、旧 64 字节头无写打开及首次长键升级、密集旧配置边界与超限写前拒绝。无正文或长行存储改动。 +- examples/blog/test-business.py 以真实本机服务和 ChuBlog 固定 Rust 驱动完成 seed、重启 verify 及停机备份副本 verify,账户哈希、授权版本、评论、互动计数及审计均保留;临时业务目录和副本自动清理。日志为 logs/blog-business-driver.log。 +- Dockerfile 的 Debian 源改为 http://mirrors.tencentyun.com,按用户要求未验证或重建镜像;既有 Docker 验收结果只适用于上节固定镜像。接入方式及应用边界见 docs/blog-database.md。 + +### 行版本、并发与在线迁移 + +- 持久化 mvcc.json 记录格式版本、提交序号、不复用行编号、可见起止序号、内容版本与逻辑行序。默认快照隔离与自身修改可见,SERIALIZABLE 写事务按表复查读依赖;旧目录首次事务或写入前导入,原堆页格式不变。堆 / 索引同步后原子发布版本目录,再推进检查点;重启重放幂等发布,版本超前于可恢复 WAL 时拒绝打开。 +- 行锁和旧 / 新唯一值锁跨请求持有,NULL 不争用唯一值锁。等待图检测环、5 秒总等待超时、显式取消与存储恢复封闭均可释放或唤醒等待者;deadlock_detected、lock_timeout 和 serialization_failure 保留结构化错误码。保存点回滚同步最终计划与读依赖,锁保留到事务结束;断线和重新认证清理旧事务。 +- 同库数据准备共享执行门,最终校验和 WAL 发布使用短提交门;其他库可独立推进。内部行编号用于合并与冲突,内容版本避免其他行位置移动造成伪冲突;整数 id 可增量物理写入,其余情况保留整表写入兼容。事务结束回收内存旧版本,后续发布回收磁盘版本;原始管理员写入通过发布版本参与冲突检查。 +- database_snapshot 保留完整结构 / 数据与提交点返回、相同令牌 snapshot_unchanged 及最近一个库的缓存;SQL 事务另行登记快照存活期,不依赖缓存保留旧版本。工作行集仍整库物化,不宣称按需版本索引扫描或增量版本日志。 +- 页与索引页写入前同步 CPW1 全页镜像,数据同步后发布版本 1 的 .pages 元数据,再清理 .page-wal。页 LSN 关联逻辑 WAL 提交点,独立写序号区分同一提交内多次页写;旧无元数据页文件按既有格式打开,首次写入建立元数据。 +- 回归验证撕裂数据页修复、重复打开幂等、未完整尾帧丢弃、完整镜像校验失败保留材料、截断后旧页不复活、镜像 I/O 失败后禁止继续刷新,以及小缓存淘汰时镜像量不随缓存页数重复放大。页大小、堆和索引页内布局未变;备份须保留整个目录,新版写入后不得降级旧二进制。 +- 逻辑恢复在重放已提交组前重建受影响的派生索引,整表日志直接重写,残缺索引根不再阻断恢复。账号初始化与变更也使用带提交标记、检查点和页 LSN 的普通提交组;旧账号 WAL 仍可恢复。文件删除和改名同步处理页元数据与镜像,并传播发布路径 I/O 错误。 +- 显式 compact 在线复制影子堆与全部索引,最终写门内追平并发修改,经 Migrate WAL 切换 catalog.file_generation,逻辑对象与结构版本保持不变。旧快照保留退役文件,结束后回收;重启恢复后清理孤立代次。固定并发窗口验证复制期间删除、更新、新增和行序保持;验证提交切换日志后、发布 catalog 前的中断可幂等恢复。启动隐藏列整理保留离线兼容路径。 +- 版本与锁专项验证不同行合并、等待后旧版本拒绝、死锁中止、锁超时、等待取消、旧版本引用回收、SERIALIZABLE 幻行拒绝和重启读取。在线整理回归验证文件缩小、隐藏字节回收、旧快照结束前旧文件保留及重启索引点查。 +- 实际 ChuBlog Rust 驱动业务验收后连续提交关联明细与计数,收到十次回执后强杀一次性服务;重启保留全部十次已确认提交,明细 / 计数一致,停机备份副本再次通过。日志为 logs/mvcc-driver-final.log;不据此承诺真实断电或任意介质损坏恢复。 +- 本阶段源码动态库、全量门禁、补充 Rust 回归、实际驱动业务 / 并发 / 强杀恢复、HLint、Fourmolu 与差异空白检查通过;日志为 logs/mvcc-stage-gate-final.log、logs/mvcc-lifecycle.log、logs/mvcc-hlint.log。未重建 Docker 镜像,ChuBlog 实现未修改。 diff --git a/.agents/context/side-branch-plan.txt b/.agents/context/side-branch-plan.txt index ad0178e..6392f59 100644 --- a/.agents/context/side-branch-plan.txt +++ b/.agents/context/side-branch-plan.txt @@ -1,16 +1,69 @@ -ChuSQL 近期任务与依赖 +# ChuSQL 近期任务与依赖 -实现、测试及门禁状态只以 progress.txt 为准;设计见 design-decisions.txt,限制见 known-issues.txt。 -下列顺序是规划,不是已完成能力;每批按实际进度选择任务。 +本计划帮助开发者按个人博客落地所需的顺序推进数据库。实现、测试及门禁状态只以 progress.txt 为准;设计见 design-decisions.txt,限制见 known-issues.txt。 +下列顺序是规划,不是已完成能力;按大阶段交付,阶段内运行受影响模块测试,较大改动完成后运行全量门禁。 -1. 统一绑定与类型系统:完成多级作用域、来源/列身份、写语句和约束绑定,收拢旧兼容桥;完善 DOMAIN 约束与 ALTER DOMAIN、精确 DECIMAL、复合类型 Eq / Ord / Hash,再推进 ENUM / 用户复合类型 / ADT。统一写入、导入、事务提交与 Rust 索引语义,保留 nullable、错误时序和布局语义;明确整数范围、CHAR、旧目录身份升级及数据迁移。已有 schema 版本和读取守卫的验收见 progress.txt。 -2. 查询语言与执行优化:推进递归 CTE 和写入型 CTE,扩展复杂条件去相关,完善物化内存预算及磁盘溢出,合并连接搜索、外连接变换及统计成本改进;写入型 CTE 依赖统一写入校验。优化保持行序、重复、错误时序及来源解析规则。 -3. 原子结构变更与范式迁移:将库建删、DDL、对象依赖及版本复查纳入原子发布和恢复,维护绑定失效、权限、回滚与编号高水位;在对象目录、DOMAIN 约束及结构事务基础上支持 CASCADE 和范式自动迁移,发布前验证旧数据与嵌套依赖。迁移首版保留来源,拒绝 NULL、重复行及依赖不保持,后续推进多轮分解。 -4. 存储并发与恢复:推进 MVCC、死锁检测和并行写,完善页 LSN、恢复、跨页整理及隐藏列重写。保留幂等、隔离、句柄生命周期、行序与资源预算,以实测决定并行扩展。 -5. 权限与客户端能力:完善列级权限、所有权转移、ADMIN OPTION 和身份属性;统一 Web 复合值编辑、大整数及多页面事务的交互与会话约束。按真实需求选择实施范围。 +## 1. 数据库可靠性与部署验收 + +以 ChuBlog 最新 TODO.md 的优先级为准;其 PLAN.md 保留原始规划,不能据此排除账户、评论、互动或内部文章需求。先验证现有数据库和驱动,再承接不可重建的业务数据。 + +完成现有多阶段 Dockerfile 的完整源码镜像构建,在受限 Buildx 或异机构建后导入,避免在 WSL 无限制并行编译。验证该镜像的首次引导、非 root 运行、健康检查、卷权限、重启持久化、升级及备份恢复,并固定通过验收的版本与镜像 digest。 + +在实际镜像上执行持续负载、并发冲突、进程崩溃、磁盘满及提交失败恢复验证,区分已确认提交、失败和断线后提交结果未知。验证驱动连接、超时、错误传播及回滚行为;未知提交结果不能直接重试非幂等操作。先处理发现的数据一致性缺陷,不要求先实现完整 MVCC。 + +在副本演练备份恢复,区分可从 Git 重建的文章索引与必须恢复的业务数据。域名、公网证书、SSH 发布、Git 硬配额和整站加密备份属于 ChuBlog 部署工作,数据库阶段提供相应验证支持,不替代整站验收。 + +## 2. 博客业务持久化与驱动联调 + +覆盖用户、Argon2id 密码哈希及参数、角色、发布授权和迁移;支持 BANNED / MEMBER / AUTHOR / MASTER 所需的业务数据。角色继承、文章所有权及撤权后的会话 / SSH 发布失效由博客服务端落实,不要求为每名读者创建数据库身份。ENUM 先评估驱动兼容性,可用现有标量字段及 CHECK 约束交付,不作为默认前置条件。 + +核对实际字段、SQL 和协议需求,验证并发注册唯一性、业务关联写入及权限变更的原子性。现有多请求写语句缺少整条语句的数据快照与冲突检查,须验证显式事务能否满足这些场景,并补齐必要的数据库或驱动缺口;不能把单次存储操作持锁等同于整条 SQL 原子性。 + +保存内部文章可见性、查阅口令的加盐慢哈希及授权撤销版本、站长隐藏 / 删除 / 精华状态和管理审计。将这些权威业务状态与可重建文章索引分开,验证作者再次推送、索引重建或恢复不会覆盖站长管理决定;数据库或身份查询失败时拒绝受保护访问。哈希计算、限流及正文 / 资源访问控制由博客实现。 + +验证评论的作者 / 文章关联、时间、管理状态、分页和必要索引,以及匿名 / 登录身份关联、重复提交与点赞 / 收藏去重所需的持久数据。并发新增、取消、删除及计数更新须保持约定的一致性,避免重复计数、丢失更新和负数;热度权重、时间衰减、防刷及保留规则由博客定义,数据库验证聚合、排序和重算所需能力。按实际查询检查稳定分页、可见性过滤与资源消耗。 + +正文和资源落盘为文件,不存入数据库;长行 / 溢出存储不属于博客需求。评论虽然入库,也不据此引入长行支持:由博客明确字数、UTF-8 字节数、请求体和累计配额,数据库按实际整行编码验证容量。按实际索引字段验证 64 字节键限制,只有实际超限时才补所需标量长键支持,不截断或静默丢值。 + +使用 ChuBlog 的 Rust 驱动完成上述数据库场景联调及账户迁移、业务备份恢复验证。博客实现和旧文件迁移属于 ChuBlog 的配套工作,修改该仓库前遵循其开发约束;前两个阶段完成表示数据库满足已验收的博客场景,不代表博客前端、审核或所有后续功能已完成。 + +## 3. 存储并发与恢复扩展 + +本阶段范围为持久化行版本、快照引用与回收、行锁和唯一键锁、等待 / 取消与死锁、同库并行准备、连续 WAL 发布,以及影子文件在线迁移与恢复。实现和验收状态只见 progress.txt。 + +后续性能工作根据实测减少整库物化、版本文件写放大和最终切换窗口,保留隔离、行序、句柄生命周期和恢复约束;不把这些优化混同于未完成基础并发能力。 + +## 4. 统一绑定与类型系统 + +在已有多级词法作用域、查询和写入绑定基础上,完善独立来源 / 列身份及约束绑定,收拢旧兼容桥。 + +在 DOMAIN 约束、ALTER DOMAIN 和内建复合类型 Eq / Ord / Hash 的基础上,推进精确 DECIMAL、复合索引键编码及用户运算实现,再推进枚举(ENUM)、用户复合类型和代数数据类型(ADT)。博客若采用 ENUM,须连同驱动映射另行验收,不作为账户持久化的默认依赖。 + +统一写入、导入、事务提交与 Rust 索引语义,保留 nullable、错误时序和布局语义;明确整数范围、CHAR、旧目录身份升级及数据迁移。已有 schema 版本和读取守卫的验收见 progress.txt。 + +## 5. 原子结构变更与范式迁移 + +将库建删、DDL、对象依赖及版本复查纳入原子发布和恢复,维护绑定失效、权限、回滚与编号高水位。 + +在对象目录、DOMAIN 约束及结构事务基础上支持 CASCADE 和范式自动迁移,发布前验证旧数据与嵌套依赖。 + +迁移首版保留来源,拒绝 NULL、重复行及依赖不保持,后续推进多轮分解。 + +## 6. 查询语言与执行优化 + +推进递归 CTE 和写入型 CTE,扩展复杂条件去相关,完善物化内存预算及磁盘溢出,合并连接搜索、外连接变换及统计成本改进;写入型 CTE 依赖统一写入校验。 + +优化保持行序、重复、错误时序及来源解析规则。博客基线查询若出现资源耗尽或性能问题,先按实测补必要预算或优化,不等待本阶段整体完成。 + +## 7. 权限与客户端扩展 + +完善数据库列级权限、所有权转移、ADMIN OPTION 和身份属性;统一 Web 复合值编辑、大整数及多页面事务的交互与会话约束。 + +按真实需求选择实施范围。博客业务用户与角色由博客表及应用授权管理,不要求为每名读者创建数据库登录身份;现有数据库权限不足以隔离博客服务账号时,必要修复提前到博客业务联调阶段。 + +## 持续验收 -持续验收 - 局部改动通过受影响模块测试;较大改动由 agent 执行全量门禁,通过后再提交。模块测试不替代异常恢复、磁盘错误、持续负载及并发冲突演练。 -- sudo、在线安装、Linux $ORIGIN、macOS 构建发行与发布签名按目标平台验证,结果登记 progress.txt。 -- 升级明确账号/授权/配置迁移、禁止降级、旧历史和异常凭据清理;不承诺旧二进制兼容、损坏页自动修复或任意 OS 用户映射。 +- sudo、在线安装、Linux $ORIGIN、macOS 构建发行与发布签名按目标平台验证,结果登记 progress.txt;非博客部署目标的平台验收不阻塞博客接入。 +- 升级明确账号 / 授权 / 配置迁移、禁止降级、旧历史和异常凭据清理;不承诺旧二进制兼容、损坏页自动修复或任意 OS 用户映射。 - Haskell 构建串行,存储协议变化重建实际动态库;门禁入口为 gate-check/run-gate.ps1。 diff --git a/.agents/skills/chusql-boundary-contracts/SKILL.md b/.agents/skills/chusql-boundary-contracts/SKILL.md index 00342a8..6b5eeca 100644 --- a/.agents/skills/chusql-boundary-contracts/SKILL.md +++ b/.agents/skills/chusql-boundary-contracts/SKILL.md @@ -5,14 +5,16 @@ description: 修改 ChuSQL Rust/Haskell FFI、客户端与 Server 协议、跨 # ChuSQL 边界契约 -## Scope +## 适用范围 负责组件间表示、调用与生命周期。类型内容使用 chusql-type-system,落盘与恢复使用 chusql-storage-integrity,通用 unsafe 检查使用 rust-c-ffi-safety。路径相对仓库根目录,按变更读相关消费者。 -## Architecture +## 模块与调用路径 - CLI / Web 后端通过 `chusql-interface/src/ChuSQL/Interface/Link.hs` 连接 Server TCP;`Protocol.hs` 定义网络消息,`Session.hs` 提供客户端会话操作。 -- `chusql-server/src/ChuSQL/Server/TCP.hs` 分派消息,`Session.hs` 管登录 / 鉴权,`Backend.hs` 调引擎。浏览器通过 `chusql-web/src/ChuSQL/Web/API.hs` 的 HTTP API 访问 Web 后端,不直接访问 Rust。 +- `chusql-server/src/ChuSQL/Server/TCP.hs` 分派消息,`Session.hs` 管登录 / 鉴权,`Backend.hs` 调引擎。 + + 浏览器通过 `chusql-web/src/ChuSQL/Web/API.hs` 的 HTTP API 访问 Web 后端,不直接访问 Rust。 - `chusql-core/engine/src/ChuSQL/Core/Engine/Storage/IPC.hs` 将 MonadStorage 操作编码为 JSON,经 localStorageLink 调 FFI;IPC 名称不表示当前另起存储进程或 Socket 服务。 - FFI 两端是 `chusql-core/engine/src/ChuSQL/Core/Engine/Storage/FFI.hs` 与 `chusql-core/storage/src/ffi.rs`,方向 Haskell → Rust,没有回调 ABI。 - 存储 JSON 定义于 `chusql-core/model/src/ChuSQL/Core/Protocol.hs` 与 `chusql-core/storage/src/protocol.rs`;它与 Interface TCP 属于不同协议。 @@ -27,38 +29,49 @@ description: 修改 ChuSQL Rust/Haskell FFI、客户端与 Server 协议、跨 | open | const char* → Storage* | NULL 路径用默认;失败 NULL,成功由 close 归还 | | close | Storage* → void | NULL 安全;非空句柄只关闭一次 | | request | const Storage*, const u8*, usize, u8**, usize* → i32 | 输入借用;输出由 Rust 分配;0 / -1 | -| maintenance | const char*, const u8*, usize, u8**, usize* → i32 | 离线操作;响应 ownership 同 request | +| maintenance | const char*, const u8*, usize, u8**, usize* → i32 | 离线操作;响应所有权同 request | | free | u8*, usize → void | 归还原始指针 / 长度对,不跨分配器、不重复释放 | | last_error | usize* → const u8* | 借用线程局部错误,立即复制、不释放 | -## Invariants +## 必须保持的不变量 + +### 表示与指针 - 路径为 NUL 结尾 UTF-8;请求 / 响应为显式长度 UTF-8 JSON,响应不保证 NUL 结尾,不能用 C 字符串函数读取。 - Haskell request 使用 Ptr CChar、CSize、Ptr (Ptr CChar)、Ptr CSize 并返回 CInt,maintenance 以 CString 替代句柄。改签名同步两端与实际动态库。 -- 借用指针整个调用中有效,输出可写且不与输入或其他输出重叠。Rust 拒绝 NULL / 超过 isize::MAX 的请求长度,但不能验证非空指针的分配范围 / provenance;catch_unwind 不是非法指针保护。 +- 借用指针整个调用中有效,输出可写且不与输入或其他输出重叠。Rust 拒绝 NULL / 超过 isize::MAX 的请求长度,但不能验证非空指针的分配范围 / 来源合法性(provenance);catch_unwind 不是非法指针保护。 + +### 所有权与错误 + - 成功输出是 Box<[u8]> 转出的所有权;Haskell callStorage 复制后 finally 调 free,失败清空输出。保留取消屏蔽,避免复制 / 释放窗口泄漏。 - open / request / maintenance 捕获 Rust panic,经 NULL / -1 和 last_error 返回;业务错误也可能是 ABI 成功响应中的 JSON error,两层失败都要处理。 - close / free 捕获析构 panic 但没有状态返回,当前忽略捕获结果;不能依靠析构保证提交或宣称它报告落盘失败。 + +### 线程与句柄 + - onStorageThread 在支持 bound threads 的 RTS 中绑定调用和错误读取到同一 OS 线程;last_error 缓冲只到本线程下次设置错误前有效。 - Haskell open / close / request / maintenance 是 safe ccall,version / free / last_error 是 unsafe ccall;长 I/O 不改为 unsafe。请求期间不得关闭句柄。 - IPC 的 withStorageLink 计数在途请求,closeConnection 等空闲再关闭;不绕过它更换 / 释放链路。Env 保存会话工作库,不把全局默认库当多连接状态。 + +### 消息与消费者 + - Interface TCP 是一行 UTF-8 JSON,Hello 校验 protocolVersion=1;同一 Client 的 MVar 串行化请求 / 响应。Server 每连接建 Session 并限制行长度,客户端锁不是全局数据库锁。 - SchemaColumn 字段、method / status 标签、缺省字段、错误码及 QueryResult columns / rows 的位置关系是消费者契约,不用自动派生构造器名替代稳定标签。 - 复合值标签为 __chusql_runtime_v1,由 Core.Runtime 编解码;Rust 行仍是通用 JSON。封装变化检查 CLI / Web / 存储重载,Web 数值受 JavaScript 安全整数限制。 - 原始存储透传仍经过 Server 会话鉴权;新入口核对 TCP 分派、会话策略与 Web 消费者,不绕过对象权限或业务错误。 -## Engineering Decisions +## 实现取舍与边界 优先扩展共享协议与真实调用者,不增加无用途适配层;确认无人依赖的内部接口可直接调整。新增类型化值沿 JSON 载荷传递,只有实际需要才扩展 ABI。 Rust panic、Haskell IO 失败与业务错误按边界转成明确失败;当前没有自动 ABI 兼容协商或后台回调生命周期管理。 -## Validation +## 验证入口 - ABI / ownership 变更验证 `chusql-core/storage/tests/ffi_test.rs` 的成功、错误、长度、编码和释放路径;必要时用可用 Miri,不为普通消息变更强制安装工具。 - 存储协议变化测试相关 Rust 模块并重建实际 cdylib,再串行验证受影响 Haskell 模块;rlib 或 mock 不能证明实际 FFI 可用。 - TCP 改动验证 Hello、错误响应和真实消费者,复用 `chusql-server/test/Spec.hs`、`chusql-web/test/Spec.hs`、`chusql-cli/test/Spec.hs` 中相关行为。 - 入口见 `gate-check/run-step.ps1`,测试范围按风险决定,不自动运行所有者全量门禁。 -## References +## 相关资料 Web 值展示 / SQL 生成消费者见 `chusql-web/static/core.js`;总体路径见 `docs/architecture.md`。核对协议时读两端编码 / 解码和调用者,不依赖绝对行号。 diff --git a/.agents/skills/chusql-storage-integrity/SKILL.md b/.agents/skills/chusql-storage-integrity/SKILL.md index c1b458e..f715b8c 100644 --- a/.agents/skills/chusql-storage-integrity/SKILL.md +++ b/.agents/skills/chusql-storage-integrity/SKILL.md @@ -5,49 +5,64 @@ description: 修改 ChuSQL 存储页、索引、序列化、catalog、系统元 # ChuSQL 存储完整性 -## Scope +## 适用范围 负责持久化状态及其与服务端事务的关系。类型语义使用 chusql-type-system,接口生命周期使用 chusql-boundary-contracts;不照搬 PostgreSQL 内核设计。路径相对仓库根目录,只读受影响模块。 -## Architecture +## 模块与调用路径 - `chusql-core/storage/src/runtime.rs`:Storage 持有数据目录文件锁、管理数据库;Server 管每库 catalog、WAL、表缓存和读写门。 -- 数据根目录中 system/ 保存系统库,databases// 保存业务库。每库有 catalog.json、.db、内建
.idx、其他
..idx、wal.log 与 wal.checkpoint;诊断日志由 log_files 单独配置。 +- 数据根目录中 system/ 保存系统库,databases// 保存业务库。 + + 每库有 catalog.json、mvcc.json、
.db、内建
.idx、其他
..idx、wal.log 与 wal.checkpoint;非空 file_generation 使用
.g<代次> 前缀;页文件另有 .pages、.page-wal 和可能残留的 .pages.pending,备份复制整个目录;诊断日志由 log_files 单独配置。 - `chusql-core/storage/src/page.rs` 管定长页与缓存刷盘;`heap.rs` 管页内槽位、JSON 行、隐藏列和 compact;`btree.rs` 管变长字节键、重复键与叶子链范围扫描。 - `chusql-core/storage/src/catalog.rs` 管 schema、索引、统计、隐藏列、对象编号 / 高水位;`protocol.rs` 定义线上 schema 和系统表常量。 +- `chusql-core/storage/src/mvcc.rs` 管持久化行版本、稳定行编号、快照引用、行 / 唯一键锁、等待图与回收。 - `chusql-core/storage/src/wal.rs` 管 LSN、提交组、日志扫描与检查点;runtime.rs 的 group_via_wal、recover_wal、replay_op 连接记录与应用。 -- `chusql-server/src/ChuSQL/Server/Session.hs` 管会话快照、保存点、差分与冲突;`Backend.hs` 向存储提交操作。`chusql-bootstrap/` 调用 Storage::maintenance 与 maintenance_candidate 做离线维护。 +- `chusql-server/src/ChuSQL/Server/Session.hs` 管会话快照、保存点、差分与冲突;`Backend.hs` 向存储提交操作。 -## Invariants + `chusql-bootstrap/` 调用 Storage::maintenance 与 maintenance_candidate 做离线维护。 + +## 必须保持的不变量 + +### 目录与提交顺序 - 表存在性以 catalog 为准,文件存在不表示已登记;不能靠打开文件创建逻辑表。语义与优化只读取 schema。 - Catalog::save 写 pending 文件、同步后替换;单文件替换不等于 catalog、页与索引已整体原子提交。 -- 普通组先 append_group 落盘,再设置 recovery_required,然后应用、刷表、推进检查点、截断日志,全部成功才解除恢复状态。 +- 普通组先 append_group 落盘,再设置 recovery_required,然后应用、刷表、原子发布行版本目录、推进检查点、截断日志,全部成功才解除恢复状态。 - 应用 / 刷盘 / 检查点 / 截断失败必须保持恢复状态并报错。普通业务请求被阻断;Ping / SystemStatus 例外由各自分派层处理,新增入口不得绕过状态。 - 恢复仅重放检查点之后已提交组,保持 replay_op 幂等;不应用未提交组。现有 WAL 是 redo,检查点是库级 LSN,不是 undo 或页级恢复。 -- 账号引导 / 变更存在独立 WAL 路径,不能假定所有写入都走普通组函数。 +- 账号引导 / 变更已走普通带提交标记的组;旧账号 WAL 仍须兼容恢复,不删除既有解码和迁移规则。 +- 全页镜像先同步,再覆盖页文件;数据同步后发布页 LSN 元数据,最后清理镜像。镜像用独立写序号区分同一提交内的重复页写,错误后当前页句柄不得继续刷新。 + +### 身份与生命周期 + - 库 / 表对象和身份编号依赖持久化高水位,删除后不复用;迁移不能降低计数器,不能从现存对象推断已删除编号上限。 - 系统身份 / 凭据、角色、授权、类型与 DOMAIN 元数据保持对应关系。引导保留已有口令和降权状态,拒绝定义 / 保留文件冲突;类型目录不是可动态扩展基础类型的机制。 -- 数据目录锁覆盖存储和维护生命周期;维护前停止占用进程。每库读共享 / 写独占、表句柄加锁,不假定同库跨表并行写。 -- 会话事务是整库内存快照,无嵌套事务,事务内禁止 DDL / USE。提交跳过未修改表,整数 id 按键差分,否则整表比较 / 替换;对象身份和权限需复查,冲突返回 serialization_failure 并保留事务。 +- 数据目录锁覆盖存储和维护生命周期;维护前停止占用进程。同库行修改可并行准备,行锁等待不占提交门;最终 WAL 发布、页刷盘和版本发布仍串行,表句柄加锁。 + +### 事务与格式 + +- SQL 使用持久化行版本快照,工作行集仍整库物化,无嵌套事务,事务内禁止 DDL / USE。提交按内部行编号合并,整数 id 可差分物理写入,否则整表替换;对象身份、权限和最终约束需复查。行锁等待图中止环的新等待者,5 秒总等待超时;保存点回滚不释放已有锁。错误后调用方回滚,不能只重发 COMMIT。 - 页内 compact 保留槽位编号与索引位置;隐藏列 compact 可能整表重写。布局、键编码、行序和隐藏列改动须检查真实消费者。 - 页大小、B+Tree magic / 布局、槽位小端字段、JSON 行、WAL 标签 / 帧和 catalog 字段是格式契约。改变前明确加载、迁移或拒绝策略,不以重新初始化掩盖不兼容。 -## Engineering Decisions +## 实现取舍与边界 - 优化可减少分配或重复读取,但保留验证、刷盘顺序、错误传播与可观察行序。结构变更同时核对 WAL、应用、幂等恢复与 catalog 保存。 - 数据库目录建删不走普通表 WAL,删库使用墓碑目录;不能承诺表提交组相同的崩溃原子性。 - 离线维护在候选目录操作并保留备份;repair 不改既有表数据,recover 依赖可用 WAL,reset 重建系统目录且保留业务库。失败保留原目录 / 恢复材料。 -- 当前 Catalog::load 对不存在或空文件返回空目录,JSON 损坏报错;不能宣称所有损坏都会拒绝。rename_table_files 和部分析构 / 清理路径仍忽略 I/O 错误,不作为成功持久化保证。 -- 尚无行版本 MVCC、页级恢复、跨页填洞、并行写或通用结构迁移事务,不据此放松校验。 +- 当前 Catalog::load 对不存在或空文件返回空目录,JSON 损坏报错;不能宣称所有损坏都会拒绝。文件发布路径改名与删除须同时维护页侧文件并传播错误;部分析构 / 清理路径仍可能忽略 I/O 错误,不作为成功持久化保证。 +- 在线 compact 复制影子堆 / 索引,最终库写门内追平,经 Migrate WAL 切换 file_generation;影子文件先同步,catalog 再发布。快照结束后回收退役文件,启动先恢复再清理孤立代次。对象编号、schema 版本和逻辑行序不变;同名重建不能复用仍被快照保留的旧文件。 +- 行版本以提交 LSN 为可见序号,内容变化和行序变化分开;版本超前于可恢复 WAL 时拒绝打开。旧版本保留到最老活跃快照,不复用行编号。尚无通用结构迁移事务,不据此放松校验。 -## Validation +## 验证入口 - 按影响选择 `chusql-core/storage/tests/` 的 page / heap / btree / catalog / wal / runtime 测试;说明修正核对源码即可。 - 格式 / 元数据 / WAL 改动验证重开、提交前后中断、重复恢复、缺失 / 截断 / 损坏输入与失败后状态;断言须检测实际不一致。 - 会话差分 / 冲突变更还验证 `chusql-server/test/Spec.hs`;并发压力测试不是正确性证明。 - 规定入口为 `gate-check/run-step.ps1 -Kind cargo`,动态库构建为 -Kind build;受影响 Haskell 模块按脚本命令串行构建,全量门禁遵守 AGENTS.md。 -## References +## 相关资料 恢复操作按需读 `docs/bootstrap.md`,配置见 `docs/config.md`,限制见 `.agents/context/known-issues.txt`;涉及拟议能力时仍以源码为准。 diff --git a/.agents/skills/chusql-type-system/SKILL.md b/.agents/skills/chusql-type-system/SKILL.md index 6aff395..883a8b3 100644 --- a/.agents/skills/chusql-type-system/SKILL.md +++ b/.agents/skills/chusql-type-system/SKILL.md @@ -5,44 +5,57 @@ description: 修改 ChuSQL SQL 类型、值表示、赋值转换、类型推导 # ChuSQL 类型系统 -## Scope +## 适用范围 负责类型语义;落盘顺序交给 chusql-storage-integrity,传输契约交给 chusql-boundary-contracts。通用语言与测试规范使用已有 Skills,不重复加载。下列路径相对仓库根目录,只读本次相关模块。 -## Architecture +## 模块与调用路径 - `chusql-core/model/src/ChuSQL/Core/Model.hs`:`ColumnType`、列约束、`Value`;集中提供 `assignable`、`comparableTypes`、`valueFits`、`coerceValue`、相等与哈希语义。 - `chusql-core/model/src/ChuSQL/Core/Runtime.hs`:`TypeExpr` / `TypeId`、`Kind`、独立 `PhysicalType`、`RuntimeValue`、注册表和版本化编码;Engine 的 `Runtime/Types.hs` 只是重新导出。 - `chusql-core/engine/src/ChuSQL/Core/Engine/Syntax/Parser.hs` 与 `Syntax/AST.hs` 解析声明和构造表达式;`Semantic.hs` 根据 schema 解析 DOMAIN、推导表达式并绑定身份。 - `chusql-core/engine/src/ChuSQL/Core/Engine/Runtime/Functions.hs` 定义固定 FunctionId 与签名,现有函数 length / not;`Runtime/SQL.hs` 连接 SQL 标量和运行时值。 -- `chusql-core/engine/src/ChuSQL/Core/Engine/Runtime/Query.hs` 的 BoundQuery 保存 schema、输出类型和优化后的 RelOp,执行后按位置校验。`Runtime/Binding.hs` 另提供类型化表达式与基础计划,尚未替代完整 SQL 关系代数。 +- `chusql-core/engine/src/ChuSQL/Core/Engine/Runtime/Query.hs` 的 BoundQuery 保存 schema、输出类型和优化后的 RelOp,执行后按位置校验。 + + `Runtime/Binding.hs` 另提供类型化表达式与基础计划,尚未替代完整 SQL 关系代数。 - `chusql-core/model/src/ChuSQL/Core/Protocol.hs` 共享值的 JSON 转换;Rust 的 `chusql-core/storage/src/protocol.rs` 使用 `HashMap` 保存行。 -## Invariants +## 必须保持的不变量 + +### 类型身份与值 - 构造器编号固定:Int=1、Double=2、Bool=3、String=4、List=5、Maybe=6、Tuple=7。使用 resolveType 检查参数 / kind,不把显示名当身份,不再维护第二份注册表。 - CRuntime / VRuntime 身份必须匹配;递归检查列表元素、Maybe 内容与元组字段数,Double 必须有限。保留逻辑类型与物理表示的区别。 - SQL VNull 与 RMaybe Nothing 不同;CNull 是查询推导类型,不能声明为存储列。保留三值逻辑与函数 NULL 传播。 + +### 转换与数值语义 + - 赋值兼容和比较兼容分别使用 Model 入口。coerceValue 负责值收敛;整值浮点转整数、字符串长度、日期格式、DECIMAL 舍入沿现有规则处理,不在 Parser / Eval / Web 重复实现转换。 -- 整数与可规范化整值浮点保持相等 / 哈希一致。底层 compareValue 的实现不表示 SQL 已开放该类型的比较、排序、分组或索引。 +- 整数与可规范化整值浮点保持相等 / 哈希一致。内建运行时类型的 Eq / Ord / Hash 由 TypeDescriptor 按参数递归派生,排序和哈希按结构实现;索引键编码仍独立,不能因已有查询能力放开索引或唯一键声明。 + +### 领域与兼容表示 + - DOMAIN 使用 domainTableName 与目录定义解析基础类型、依赖及循环;不能拿解析器占位基础类型直接执行。系统内建类型目录也不是通过增加行即可扩展的插件注册表。 - Date / Timestamp / Blob 在 QueryType 保留 CompatibilityType;ColumnType 与 RelOp 仍有真实消费者,不能作为无用兼容层删除。 + +### 编码与错误传播 + - 类型 / 值编码版本为 1;身份、类型名、封装或值结构变化可能影响 catalog、WAL、FFI、TCP 和 Web,组合相关 Skills 核对消费者。 -- Rust 当前保存通用 JSON,只做局部校验(隐藏列、DOMAIN 依赖、DECIMAL 规范化),没有 Haskell validateValue 的完整等价检查;不要依赖原始存储请求完成所有 SQL 类型校验。 +- Rust 当前保存通用 JSON,只做局部校验,包括隐藏列、DOMAIN 依赖和 DECIMAL 规范化。它没有 Haskell validateValue 的完整等价检查,不要依赖原始存储请求完成所有 SQL 类型校验。 - 错误沿 Either String 返回;`chusql-core/engine/src/ChuSQL/Core/Engine/Error.hs` 用消息规则映射类别 / 协议码。修改错误文字须检查分类,不用默认值或 NULL 掩盖错误。 -## Engineering Decisions +## 实现取舍与边界 -复用 Model / Runtime 的语义入口,在现有类型桥上做最小修改。尚无完整 capability / operator / cast 注册机制、通用显式 CAST、用户 ADT 或 Extension;DOMAIN 自身 CHECK / NOT NULL / DEFAULT 尚未实现。不要将规划当现有契约。 -DECIMAL 是有限浮点表示,采用 ties-to-even 舍入与舍入后溢出检查,并非精确十进制存储。运行时复合类型尚无 SQL Eq / Ord / Hash capability 字典。 +复用 Model / Runtime 的语义入口,在现有类型桥上做最小修改。尚无完整 capability / operator / cast 注册机制、通用显式 CAST、用户 ADT 或 Extension;DOMAIN 的继承约束、默认值和变更校验集中在 Engine/Domain.hs;ALTER DOMAIN 通过一致快照和提交点复查发布。不要将规划当现有契约。 +DECIMAL 是有限浮点表示,采用 ties-to-even 舍入与舍入后溢出检查,并非精确十进制存储。内建运行时复合类型已提供 SQL Eq / Ord / Hash 能力,尚无用户注册的运算实现或复合索引键编码。 -## Validation +## 验证入口 - 语义改动验证解析 → schema 绑定 → 执行,关注 NULL、边界值、明确错误与输出位置;说明修正只需核对源码。 - 复用 `chusql-core/engine/test/RuntimeSpec.hs`、`chusql-core/engine/test/Spec.hs`,按需覆盖固定编码、错误身份和嵌套值。 - 持久化类型变更验证 Rust 写入 / 重载与实际协议消费者;Web 值展示 / SQL 生成参考 `chusql-web/test/runtime-values.mjs`。 - 测试入口见 `gate-check/run-step.ps1`,不因加载 Skill 自动执行全量门禁或追求覆盖率。 -## References +## 相关资料 按需读 `docs/types.md`,区分当前类型用法与未来约束设计。以上源码模块是契约核对入口。 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5caee3f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +# 只发送构建所需源码,排除凭据、数据及宿主构建缓存。 +.git +.agents +.codex +.aws +**/.stack-work +**/target +**/dist +**/dist-newstyle +**/__pycache__ +logs +secrets +.env +.env.* +**/*.db +**/*.idx +**/wal.log +**/wal.checkpoint +Dockerfile* +compose*.yaml +docs +benchmark diff --git a/.gitignore b/.gitignore index e027a0c..b28e804 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,10 @@ learning !/.agents/skills/chusql-type-system/ /.agents/context/prompt.txt /skills-lock.json + +# Docker 部署口令仅保存在本机。 +/secrets/ +/.env +/.env.* + +examples diff --git a/AGENTS.md b/AGENTS.md index 17ed2f4..ab1bb2d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,11 +20,31 @@ - 跨领域组合相关 Skills,无关任务不加载;Skills 不覆盖更高优先级的安全和工程约束。 - 简单任务直接执行;采用最小必要改动,允许有明确收益且能验证的局部结构优化,优先删除重复和无用代码。 - 保持代码最简:用最少且易读的代码完整解决当前需求,优先复用现有实现与标准库;相同规则只维护一份,不引入仅为缩短函数或预留未来而存在的抽象、包装、配置和依赖。简化须保持求值顺序、错误传播、边界校验及恢复约束,不以压缩行数牺牲清晰度或正确性。 -- Haskell 编码后对受影响源码运行 HLint(与 nvim 的提示来源一致),修复能保持语义的建议;不通过禁用提示绕过检查。优先使用 `void`、`when/unless`、`fromMaybe`、`isJust/isNothing`、`maybeToList`、`zipWithM` 等惯用函数,避免冗余 lambda、括号、绑定、导入与 LANGUAGE pragma;涉及惰性、严格性或类型表示变化的建议须核对语义,不能机械套用。 +- Haskell 编码后对受影响源码运行 HLint(与 nvim 的提示来源一致),修复能保持语义的建议;不通过禁用提示绕过检查。 + + 优先使用 `void`、`when/unless`、`fromMaybe`、`isJust/isNothing`、`maybeToList`、`zipWithM` 等惯用函数,避免冗余 lambda、括号、绑定、导入与 LANGUAGE pragma;涉及惰性、严格性或类型表示变化的建议须核对语义,不能机械套用。 - 测试强度与实际风险及影响范围匹配,不机械新增测试,不盲目追求覆盖率;数据库内核微改动也须验证关键行为。 - 不强制 TDD、子代理或多阶段审查;减少无关读取、重复搜索、工具调用和输出,Skills 不应增加无收益的流程。 - 文档描述当前状态;不创建整改报告、修改流水账或无用途的兼容层,不修改 Git 历史。 +## 文档编写 + +编写、修改或审阅 README、`docs/` 及其他说明文档时,加载以下全局 Skills: + +- `technical-documentation`:先确定读者和阅读目的,再安排标题、操作步骤、示例与参考信息。入口为 `~/.codex/skills/technical-documentation/SKILL.md`。 +- `plain-writing`:用常用词解释行为,删除空话,拆开堆叠的术语与长句。入口为 `~/.codex/skills/plain-writing/SKILL.md`。 + +涉及设计理由时,另用 `documentation-and-adrs`,沿用现有设计文件,不另建决策或进度来源。全局目录以 `$CODEX_HOME/skills` 为准,未设置时使用 `~/.codex/skills`。 + +文档须遵守以下约定,中文不机械套用英文语法规则: + +- 开头说明本页帮助谁完成什么任务。README 先帮助安装和使用,内部实现放在架构文档中,通过链接提供深入阅读。 +- 按问题或任务分节,每段只解释一个主题,通常用 2 至 4 句。长段落优先拆分主题,不把整页改成零碎列表。 +- 有先后顺序的操作用编号步骤,并说明前提和验证结果;并列要点用列表;参数和能力对比用表格。标题、正文、列表和代码块之间留空行。 +- 必要术语首次出现时用一句中文解释,再保留准确名称。同一概念使用同一名称,不连续堆叠缩写、内部类型和函数名。 +- 命令和示例标明语言及占位符含义。链接文字说明目标内容,图示须有正文说明,不让关键信息只存在于图中。 +- 完稿后按读者顺序通读,核对链接、命令、条件、错误行为和限制。排版与措辞优化不得删掉技术边界,不为简化表达夸大能力;规划与已实现能力分开说明。 + ## 注释规范 - 文件级:外部引用语句(Haskell `import`、Rust `use`、JS `import`、HTML 的 ``/`