fix(lineage): resolve node-key targets and bare schema.table without column misparse (#154) - #156
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…column misparse (#154) 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>
…#154) Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…f dead-end fallback (#154) 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>
| let (table_name, column_name) = match column_name { | ||
| Some(column) => match graph::lineage::lookup_table_node(graph, table_name) { | ||
| graph::lineage::TableLookup::Found(_) => (table_name, Some(column)), | ||
| graph::lineage::TableLookup::Ambiguous => { |
There was a problem hiding this comment.
[suggestion] When the dotted table half is TableLookup::Ambiguous, the CLI still falls back to treating the whole target as a table reference (same recovery as Missing). For mid_yjqs_detail.nonexistent_col with that table in two schemas, the user almost certainly meant column-level lineage and only failed to schema-qualify; reinterpreting mid_yjqs_detail.nonexistent_col as a table name yields a follow-on No table found matching '…' that hides the actionable fix (qualify as schema.mid_yjqs_detail.col). The new Ambiguous variant is the right distinction, but it is not used as a terminal error.
Suggestion: On Ambiguous, print that the table name is ambiguous across schemas, tell the user to qualify (schema.table or schema.table.column), and return. Keep the Missing → whole-target table fallback only for the true schema.table mis-split case.
There was a problem hiding this comment.
Implemented in commit c8a4249. An ambiguous table half is now a terminal error with an actionable schema-qualification hint (qualify it as 'schema.X' for table-level lineage or 'schema.X.col' for column-level lineage). The whole-target fallback remains only for TableLookup::Missing, which is the true schema.table mis-split recovery path. This behavior is locked by should_say_ambiguous_when_table_half_is_ambiguous.
| target | ||
| ); | ||
| return Ok(()); | ||
| // Issue #154: `type:name` node keys (e.g. `table:schema.table`) resolve as whole |
There was a problem hiding this comment.
[suggestion] The two // Issue #154: blocks (prefix fast path and column-spec fallback) narrate the ticket, restate the branches, and embed design history. They explain WHAT the next if/match already shows rather than a non-obvious constraint.
Suggestion: Drop the issue-number / changelog narration. If a comment stays, keep one short WHY (e.g. node keys must not be last-dot-split; missing table half means the split was probably schema.table).
| /// never mistaken for `table.column` targets (#154). | ||
| pub fn split_type_prefix(target: &str) -> Option<(&str, &str)> { | ||
| let (tag, rest) = target.split_once(':')?; | ||
| if rest.is_empty() || !TYPE_TAG_PREFIXES.contains(&tag) { |
There was a problem hiding this comment.
[nit] split_type_prefix compares the tag with TYPE_TAG_PREFIXES.contains(&tag), which is case-sensitive. resolve_single_node / name_index lower-case the query, and Display tags are lowercase, so a copied key works — but Table:schema.table or TABLE:… still takes the last-dot column path and can reproduce the original misparse.
Suggestion: Compare the tag case-insensitively (e.g. eq_ignore_ascii_case against the prefix list) so the fast path matches the rest of CLI node resolution.
There was a problem hiding this comment.
Thanks. One severity correction based on the resolution path: search_nodes_limit lowercases the query (src/graph/store.rs:780) and searches the lowercase name_index, so a Table:... target still resolved correctly through the Missing fallback rather than reproducing the original misparse; the defect was the spurious fallback note. Commit 53a1361 makes type-tag detection case-insensitive, removing that note and routing mixed-case tags through the node-key fast path consistently with the rest of CLI node resolution.
| "bare schema.table should fall back to table-level lineage, got:\n{stdout}" | ||
| ); | ||
| assert!( | ||
| stderr.contains("interpreting") || stderr.contains("treating"), |
There was a problem hiding this comment.
[nit] should_fall_back_to_table_level_for_bare_schema_qualified_target accepts stderr.contains("interpreting") || stderr.contains("treating"). Production text only uses interpreting; treating cannot fail the assertion and looks like a leftover from an earlier wording.
Suggestion: Assert the actual note (interpreting plus the original target), same as the Ambiguous/Missing eprintln! format strings.
…ghten fallback assertion (#154) Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Closes #154
问题
codeweb lineage的 target 在任何节点解析之前就按最后一个.切分(src/main.rs的rsplit_once('.')),导致:codeweb lineage "table:bigfund.mid_yjqs_detail"被拆成 表=table:bigfund/ 列=mid_yjqs_detail,误入列级分支,静默返回 "No column lineage"——报错消息与用户输入字面相同,极具误导性schema.table误判:不带前缀的 schema 限定表同样被误判为table.column列级查询根因:
lineage是唯一在解析前预切分 target 的命令;trace/detail/impact均通过resolve_single_node+name_index(存NodeKeyDisplay 键,如table:schema.table)天然支持节点键语法。修复(三层增量,全部向后兼容)
src/graph/key.rs+src/main.rs):新增split_type_prefix()检测<known-tag>:前缀(标签清单与NodeKeyDisplay 实现同文件,roundtrip 单测防漂移);命中即整体作为节点键走表级分支,与其他命令语法一致src/main.rs+src/graph/lineage.rs):dot 切分出的表半部分无法解析时,回退为整体表引用;lookup_table_node()返回TableLookup { Found, Ambiguous, Missing }区分"未找到"与"跨 schema 歧义",note 措辞如实区分两种情况。表半部分可解析时列级行为完全不变(含"表存在但列无映射 → No column lineage 提示")find_table_node):schema 比较改为大小写不敏感(与表名比较一致;Bigfund.mid_yjqs_detail.amt不再因 schema 大小写不同而误触发回退)同时更新 clap help 文档节点键语法。
兼容性红线(均有测试锁定)
my_table→ 表级(不变,含子串模糊匹配与 Multiple matches 提示)table.column/schema.table.column→ 列级(不变)table:my_table→ 行为不变(原本就走表级)测试(TDD,Red → Green)
新增
tests/regress_issue_154_lineage_targets.rs(7 个行为测试):should_treat_nodekey_target_as_table_level_lineageshould_fall_back_to_table_level_for_bare_schema_qualified_targetshould_keep_column_level_for_existing_table_and_columnshould_keep_no_column_lineage_hint_when_table_exists_but_column_unknownshould_report_clean_error_for_unknown_nodekey_targetshould_resolve_column_query_with_differently_cased_schemashould_say_ambiguous_when_table_half_is_ambiguoussrc/graph/key.rs新增 3 个单元测试(含NodeKeyDisplay 标签 roundtrip 防漂移)。门禁
cargo fmt --all -- --check✅cargo clippy --features full -- -D warnings✅cargo test --features full -- --skip test_path_mapping_applied --skip test_serve_✅(671 unit + 36 套件 0 失败)