feat: 无 CREATE SEQUENCE 时为 seq.nextval 建 inferred seq* + UsesSequence(对齐 table*) - #160
Conversation
| type_index: &HashMap<String, petgraph::graph::NodeIndex>, | ||
| sequence_index: &HashMap<String, petgraph::graph::NodeIndex>, | ||
| ) { | ||
| let mut inferred_sequence_index = HashMap::new(); |
There was a problem hiding this comment.
[bug] inferred_sequence_index is a local HashMap created at the start of each create_object_ref_edges call and never written into GraphBuildContext.sequence_index. Project::analyze parses SQL in chunks of 100 (DEFAULT_SQL_CHUNK_SIZE) and calls build_sql_chunk per chunk, so the cache does not survive chunk boundaries. Tables avoid this by inserting inferred nodes into the shared table_index and by upgrading in place on CREATE TABLE (explicit = true, location = Some(...)). Sequences do neither: a later chunk that sees the same nextval/seq.nextval allocates a second seq* node, and a later CREATE SEQUENCE only checks sequence_index.contains_key(&full_key) (builder.rs:650) so it adds a sibling explicit node instead of promoting the inferred one. finalize_graph runs dedup_table_view_nodes but has no sequence equivalent, and pick_richer_node has no Node::Sequence arm, so codeweb dedup would keep the first (often inferred) node. Single-file unit tests and the issue-159 integration test never exercise two build_sql_chunk calls, so this is uncaught.
Suggestion: Keep inferred sequence lookups on GraphBuildContext (either mutate sequence_index or add a context-level inferred map) so later chunks reuse the same NodeIndex. Mirror CREATE TABLE: if a matching inferred node already exists, set explicit: true and location: Some(...) instead of add_node. Extend pick_richer_node to prefer Node::Sequence { explicit: true, location: Some(_), .. } over inferred. Add a two-chunk test in the style of qualified_table_into_view_merged_then_bare_into_qualified: chunk 1 references my_seq.nextval with no DDL, chunk 2 either repeats the ref or adds CREATE SEQUENCE my_seq, then finalize_graph and assert a single sequence node (and, in the DDL case, explicit: true).
There was a problem hiding this comment.
已修复(76725a8 + 4b0ffd4):
- ctx 级缓存:
inferred_sequence_index提升为GraphBuildContext字段(兄弟 map,不混入sequence_index),create_object_ref_edges改用共享缓存,跨 chunk 复用同一 NodeIndex - CREATE SEQUENCE 原位升级:命中推测节点时通过
graph[idx]原位改写explicit: true+location: Some(...),NodeIndex 不变、既有UsesSequence边自动指向升级后节点(petgraph 权重改写不改索引) - 升级遵守精确 key 纪律(沿用本 PR 早前修复的跨 schema 语义):限定 DDL 只升级
full_key推测节点、无前缀 DDL 只升级short_key——CREATE SEQUENCE finance.seq_id不会误升级hr.seq_id的推测节点 - dedup 兜底:
pick_richer_node补 Sequence 臂(镜像 Table 的 location 风格),merge/dedup 优先保留带 DDL 位置的节点
测试(TDD Red→Green):3 个两 chunk 回归(仿 qualified_table_into_view_merged_then_bare_into_qualified 风格:引用→DDL 升级、双 chunk 引用共享单节点、跨 schema 不误升级)+ pick_richer_node_prefers_located_sequence。其中升级测试断言既有边存活(若误删重建即失败)。
已验证:cargo build/test/clippy --features full 全绿(686 passed, 0 failed);STORE_VERSION 未变(无序列化形状变更)。含历史双节点的旧构建产物可由 codeweb dedup(现在能正确保留 explicit 侧)清理。
残余歧义(记录不处理):chunk1 无前缀推测 seq_id + chunk2 限定 CREATE SEQUENCE finance.seq_id → key 不同不升级,双节点保留——无前缀引用在推测时刻 schema 本就未知,双节点是可辩护语义。
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…sSequence 边 Node::Sequence 增加 explicit 标记与 Option<location>(对齐 Table/View 模式),推断节点由 builder 在 DDL 缺失时 or_insert 生成;schema 限定引用仅精确匹配 full key,不回退短名别名,避免跨 schema 误绑定。STORE_VERSION 8 -> 9。 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
inferred_sequence_index 原为 create_object_ref_edges 局部缓存,跨 chunk(>100 SQL 文件)即失效:同一序列产生重复 seq* 节点,且后置 CREATE SEQUENCE 只查 sequence_index 造出兄弟 explicit 节点不升级。现提升为 GraphBuildContext 字段跨 chunk 共享;DDL 命中推测节点时原位改写 explicit/location(保留 NodeIndex 与既有边),升级遵守精确 key 纪律——限定 DDL 只升级限定推测节点,杜绝短名模糊匹配跨 schema 误绑定。 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
摘要
Closes #159
seq.nextval被引用但分析范围内无CREATE SEQUENCEDDL 时,builder 此前静默丢弃UsesSequence边。本 PR 对齐table*既有模式:创建 inferredseq*节点并挂边,使detail/impact在缺 DDL 时仍能看到真实序列依赖。主要改动
src/graph/mod.rs—Node::Sequence增加#[serde(default)] explicit: bool,location改为Option<SourceLocation>(完全镜像 Table/View);node_type_tag增加seq*;Node::file()适配 Option(消除 inferred 节点 panic 路径)src/graph/builder.rs— 3 处 lookup-miss-即-丢(procedure / function / package member)收敛为共享resolve_or_infer_sequence:DDL 缺失时 or_insert inferred 节点;schema 限定引用仅精确匹配 full key,不回退短名别名,避免hr.seq_id误绑定finance.seq_id(跨 schema 误绑定 bug 在 code review 中发现并已修复,含 2 个回归测试)src/graph/store.rs—STORE_VERSION8 → 9(bincode 变体形状变更,版本门禁触发旧 store 自动重建)src/main.rs—is_inferred_node覆盖 inferred sequence,detail自动显示⚠ inferred nodesrc/export/json.rs—NodeKindJson::Sequence对齐 Table 的skip_serializing_if惯例(explicit/file/line)src/import/parser.rs— CGEF 导入的 sequence 设explicit: true测试
新增 10 个测试(TDD Red→Green):
单元(builder.rs):无 DDL 建 inferred 节点、有 DDL 恰好 1 条边不重复、
SELECT seq.nextval INTO ... FROM sys_dummy两路径、赋值/INSERT 形态、schema 限定回退、跨 schema 不误绑定 ×2其他:
seq*标签、version=8 store 被版本门禁拒绝、集成回归(落盘/增量无重复/JSON 形状)既有 2 个人类测试(
procedure_using_nextval_creates_uses_sequence_edge等)未改动,保持通过。验证
范围外(per issue)
sys_dummy/dual是否出现在 detail 默认 CALLEESmain.rs重复的node_type_tag对既有 table*/view* 不带*(pre-existing,未在本 PR 扩大范围)🤖 Generated with Sisyphus