dlin-cli 0.2.4rc1__tar.gz → 0.2.4rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/Cargo.lock +6 -6
  2. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/Cargo.toml +3 -3
  3. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/PKG-INFO +1 -1
  4. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/cross_model.rs +1 -8
  5. dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/manifest_schema.rs +302 -0
  6. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/mod.rs +25 -7
  7. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/schema.rs +1 -65
  8. dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/semantic_model.rs +377 -0
  9. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/single_model.rs +71 -13
  10. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +1 -1
  11. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_star.rs +25 -0
  12. dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/tests/core_util.rs +137 -0
  13. dlin_cli-0.2.4rc1/crates/dlin-core/src/graph/column_lineage/tests/core_util.rs +0 -33
  14. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/LICENSE +0 -0
  15. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/README.md +0 -0
  16. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/Cargo.toml +0 -0
  17. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/README.md +0 -0
  18. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/cli.rs +0 -0
  19. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/main.rs +0 -0
  20. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/mcp.rs +0 -0
  21. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/tests/integration_test.rs +0 -0
  22. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/Cargo.toml +0 -0
  23. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/README.md +0 -0
  24. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/error.rs +0 -0
  25. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/mod.rs +0 -0
  26. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/build_graph.rs +0 -0
  27. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/generic_tests.rs +0 -0
  28. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/mod.rs +0 -0
  29. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/ref_parsing.rs +0 -0
  30. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/versioned.rs +0 -0
  31. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/cache.rs +0 -0
  32. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/impact.rs +0 -0
  33. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/star_guard.rs +0 -0
  34. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_basic.rs +0 -0
  35. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_cross_model.rs +0 -0
  36. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/impact.rs +0 -0
  37. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs +0 -0
  38. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/types.rs +0 -0
  39. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/mod.rs +0 -0
  40. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/collapse.rs +0 -0
  41. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/filter_graph.rs +0 -0
  42. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/mod.rs +0 -0
  43. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/output.rs +0 -0
  44. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/search.rs +0 -0
  45. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/selector.rs +0 -0
  46. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot.snap +0 -0
  47. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_bfs_pseudoendpoint.snap +0 -0
  48. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_endpoints_fan_out.snap +0 -0
  49. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_endpoints_leaf_model.snap +0 -0
  50. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_multiple_focus_models.snap +0 -0
  51. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_no_source_exposure.snap +0 -0
  52. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot_preserve_focus.snap +0 -0
  53. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__snapshot_transitive_node_type_filter.snap +0 -0
  54. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__snapshot_transitive_select_filter.snap +0 -0
  55. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__snapshot_transitive_select_with_node_type.snap +0 -0
  56. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/transitive.rs +0 -0
  57. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/versioned.rs +0 -0
  58. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/impact.rs +0 -0
  59. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/mod.rs +0 -0
  60. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/types.rs +0 -0
  61. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/input.rs +0 -0
  62. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/lib.rs +0 -0
  63. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/cache.rs +0 -0
  64. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/columns.rs +0 -0
  65. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/discovery.rs +0 -0
  66. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/jinja.rs +0 -0
  67. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/manifest.rs +0 -0
  68. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/manifest_cache.rs +0 -0
  69. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/mod.rs +0 -0
  70. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/project.rs +0 -0
  71. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/sql.rs +0 -0
  72. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/yaml_schema.rs +0 -0
  73. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/ascii.rs +0 -0
  74. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/column_graph.rs +0 -0
  75. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/dot.rs +0 -0
  76. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/html.rs +0 -0
  77. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/impact.rs +0 -0
  78. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/json.rs +0 -0
  79. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/layout.rs +0 -0
  80. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/list.rs +0 -0
  81. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/mermaid.rs +0 -0
  82. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/mod.rs +0 -0
  83. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/plain.rs +0 -0
  84. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_all_transformation_types.snap +0 -0
  85. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_escapes_special_chars.snap +0 -0
  86. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_id_collision_avoided.snap +0 -0
  87. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_indirect.snap +0 -0
  88. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_single.snap +0 -0
  89. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_single_model.snap +0 -0
  90. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_via_path.snap +0 -0
  91. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid.snap +0 -0
  92. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid_indirect_edge_label.snap +0 -0
  93. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain.snap +0 -0
  94. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_multi_hop.snap +0 -0
  95. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_non_direct_intermediate.snap +0 -0
  96. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_dotted_table_name.snap +0 -0
  97. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_id_collision_avoided.snap +0 -0
  98. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_label_escaping.snap +0 -0
  99. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_single_model.snap +0 -0
  100. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_model_path_non_direct_annotation.snap +0 -0
  101. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_no_sources.snap +0 -0
  102. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_single_model.snap +0 -0
  103. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__group_by_node_type.snap +0 -0
  104. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_all_edge_types.snap +0 -0
  105. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb.snap +0 -0
  106. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb_grouped.snap +0 -0
  107. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_group_by_directory.snap +0 -0
  108. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_lineage.snap +0 -0
  109. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_transitive_edges.snap +0 -0
  110. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__html__tests__snapshot_html_json.snap +0 -0
  111. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json.snap +0 -0
  112. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json_with_sql.snap +0 -0
  113. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text.snap +0 -0
  114. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text_with_sql.snap +0 -0
  115. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_json_with_sql.snap +0 -0
  116. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_lineage.snap +0 -0
  117. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_node_metadata.snap +0 -0
  118. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_json.snap +0 -0
  119. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_plain.snap +0 -0
  120. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__group_by_node_type.snap +0 -0
  121. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__mixed_direct_and_transitive_edges.snap +0 -0
  122. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_escapes_quotes.snap +0 -0
  123. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_lineage.snap +0 -0
  124. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_single_model.snap +0 -0
  125. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_collapse.snap +0 -0
  126. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_grouping.snap +0 -0
  127. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb.snap +0 -0
  128. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb_grouped.snap +0 -0
  129. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_group_by_directory.snap +0 -0
  130. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_lineage.snap +0 -0
  131. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__transitive_edge_rendering.snap +0 -0
  132. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__plain__tests__snapshot_plain.snap +0 -0
  133. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_json.snap +0 -0
  134. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_text.snap +0 -0
  135. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/summary.rs +0 -0
  136. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/svg.rs +0 -0
  137. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/tests/column_lineage_test.rs +0 -0
  138. {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/pyproject.toml +0 -0
@@ -230,7 +230,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
230
230
 
231
231
  [[package]]
232
232
  name = "dlin"
233
- version = "0.2.4-rc.1"
233
+ version = "0.2.4-rc.2"
234
234
  dependencies = [
235
235
  "anyhow",
236
236
  "clap",
@@ -247,7 +247,7 @@ dependencies = [
247
247
 
248
248
  [[package]]
249
249
  name = "dlin-core"
250
- version = "0.2.4-rc.1"
250
+ version = "0.2.4-rc.2"
251
251
  dependencies = [
252
252
  "anyhow",
253
253
  "clap",
@@ -597,9 +597,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
597
597
 
598
598
  [[package]]
599
599
  name = "polyglot-sql"
600
- version = "0.6.3"
600
+ version = "0.8.0"
601
601
  source = "registry+https://github.com/rust-lang/crates.io-index"
602
- checksum = "b54acea84522c6c51f6cbfa56600097cd8c6c5583a70e67f2787b6f70c3dd956"
602
+ checksum = "6b7dd6da530087bffbf2b8b791914093b669f70eac07dbc66cf08f6954a1902e"
603
603
  dependencies = [
604
604
  "polyglot-sql-ast-derive",
605
605
  "serde",
@@ -610,9 +610,9 @@ dependencies = [
610
610
 
611
611
  [[package]]
612
612
  name = "polyglot-sql-ast-derive"
613
- version = "0.6.3"
613
+ version = "0.8.0"
614
614
  source = "registry+https://github.com/rust-lang/crates.io-index"
615
- checksum = "c19af779599f7bf0ec303044dbb8e1c3f6c5b4dca29ea703b033519860104031"
615
+ checksum = "c72cee7fdad5082a0cc73d7a9064914311fcd095b63bf5d85bd4c5b8dd89249e"
616
616
  dependencies = [
617
617
  "proc-macro2",
618
618
  "quote",
@@ -3,7 +3,7 @@ members = ["crates/*"]
3
3
  resolver = "3"
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.4-rc.1"
6
+ version = "0.2.4-rc.2"
7
7
  edition = "2024"
8
8
  license = "MIT"
9
9
  repository = "https://github.com/eitsupi/dlin"
@@ -23,7 +23,7 @@ indexmap = "2"
23
23
  minijinja = "2"
24
24
  rayon = "1"
25
25
  globset = "0.4"
26
- polyglot-sql = { version = "0.6.3", default-features = false, features = ["all-dialects", "semantic"] }
26
+ polyglot-sql = { version = "0.8.0", default-features = false, features = ["all-dialects", "semantic"] }
27
27
  path-slash = "0.2.1"
28
28
  clap = { version = "4", features = ["derive", "env"] }
29
29
  libc = "0.2"
@@ -34,7 +34,7 @@ insta = "1"
34
34
  serial_test = "3.4.0"
35
35
 
36
36
  # internal
37
- dlin-core = { version = "0.2.4-rc.1", path = "crates/dlin-core" }
37
+ dlin-core = { version = "0.2.4-rc.2", path = "crates/dlin-core" }
38
38
 
39
39
  [workspace.lints.rust]
40
40
  unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dlin-cli
3
- Version: 0.2.4rc1
3
+ Version: 0.2.4rc2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -5,6 +5,7 @@ use polyglot_sql::DialectType;
5
5
 
6
6
  use crate::parser::manifest::Manifest;
7
7
 
8
+ use super::manifest_schema::make_fq_table_name;
8
9
  use super::{
9
10
  ColumnLineageCache, ColumnLineageError, ColumnSource, ModelColumnLineage, TransformationType,
10
11
  find_model_by_name,
@@ -254,11 +255,3 @@ fn compute_single_column_lineage(
254
255
  .ok()
255
256
  .map(|r| (r.sources, r.transformation))
256
257
  }
257
-
258
- fn make_fq_table_name(database: Option<&str>, schema: Option<&str>, name: &str) -> String {
259
- match (database, schema) {
260
- (Some(db), Some(s)) => format!("{}.{}.{}", db, s, name),
261
- (None, Some(s)) => format!("{}.{}", s, name),
262
- _ => name.to_string(),
263
- }
264
- }
@@ -0,0 +1,302 @@
1
+ //! Manifest helpers that are safe to use for ordinal-aware analysis.
2
+ //!
3
+ //! The legacy YAML schema builders remain in `schema.rs`. The builder in this
4
+ //! module has a stricter contract: only a compiled query whose output order is
5
+ //! proven by polyglot-sql may become a `MappingSchema` relation.
6
+
7
+ use std::collections::HashSet;
8
+
9
+ use polyglot_sql::{DialectType, MappingSchema, Schema};
10
+
11
+ use crate::parser::cache::hash_str;
12
+ use crate::parser::manifest::{Manifest, ManifestNode};
13
+
14
+ use super::semantic_model::build_query_model_from_sql;
15
+
16
+ pub(super) fn make_fq_table_name(
17
+ database: Option<&str>,
18
+ schema: Option<&str>,
19
+ name: &str,
20
+ ) -> String {
21
+ match (database, schema) {
22
+ (Some(db), Some(s)) => format!("{}.{}.{}", db, s, name),
23
+ (None, Some(s)) => format!("{}.{}", s, name),
24
+ _ => name.to_string(),
25
+ }
26
+ }
27
+
28
+ /// Build a schema only from dependency models with a proven SQL output order.
29
+ ///
30
+ /// Manifest YAML columns are intentionally not consulted for the relation's
31
+ /// column order (or for adding a relation). A source, YAML-only model,
32
+ /// unnamed output, duplicate output name, or unresolved wildcard is omitted.
33
+ pub fn build_proven_ordered_schema(
34
+ manifest: &Manifest,
35
+ node: &ManifestNode,
36
+ dialect: DialectType,
37
+ ) -> Option<MappingSchema> {
38
+ let mut schema = MappingSchema::with_dialect(dialect);
39
+ let mut has_entries = false;
40
+
41
+ for dependency_id in &node.depends_on.nodes {
42
+ let Some(dependency) = manifest.nodes.get(dependency_id) else {
43
+ // Sources and other YAML-only relations do not prove an ordinal
44
+ // schema for this stage.
45
+ continue;
46
+ };
47
+ let Some(sql) = dependency.compiled_code.as_deref() else {
48
+ continue;
49
+ };
50
+ let Ok(query_model) = build_query_model_from_sql(sql, dialect, None) else {
51
+ continue;
52
+ };
53
+ let Some(column_names) = query_model.outputs.proven_ordered_named_outputs() else {
54
+ continue;
55
+ };
56
+
57
+ let columns = column_names
58
+ .into_iter()
59
+ .map(|name| (name, polyglot_sql::expressions::DataType::Unknown))
60
+ .collect::<Vec<_>>();
61
+ let qualified_name = make_fq_table_name(
62
+ dependency.database.as_deref(),
63
+ dependency.schema.as_deref(),
64
+ &dependency.name,
65
+ );
66
+ if schema.add_table(&qualified_name, &columns, None).is_ok() {
67
+ has_entries = true;
68
+ }
69
+ if qualified_name != dependency.name {
70
+ let _ = schema.add_table(&dependency.name, &columns, None);
71
+ }
72
+ }
73
+
74
+ has_entries.then_some(schema)
75
+ }
76
+
77
+ pub(super) fn compute_manifest_columns_hash(manifest: &Manifest, node: &ManifestNode) -> u64 {
78
+ let mut visited = HashSet::new();
79
+ hash_node_columns_transitive(manifest, node, &mut visited)
80
+ }
81
+
82
+ fn hash_node_columns_transitive(
83
+ manifest: &Manifest,
84
+ node: &ManifestNode,
85
+ visited: &mut HashSet<String>,
86
+ ) -> u64 {
87
+ let mut parts = Vec::new();
88
+
89
+ let mut own_cols = node.columns.keys().collect::<Vec<_>>();
90
+ own_cols.sort_unstable();
91
+ for column in own_cols {
92
+ parts.push(column.clone());
93
+ }
94
+ if let Some(code) = &node.compiled_code {
95
+ parts.push(format!("sql:{}", hash_str(code)));
96
+ }
97
+ parts.push("|".to_string());
98
+
99
+ let mut dependency_ids = node.depends_on.nodes.iter().collect::<Vec<_>>();
100
+ dependency_ids.sort_unstable();
101
+ for dependency_id in dependency_ids {
102
+ parts.push(dependency_id.clone());
103
+ if !visited.insert(dependency_id.clone()) {
104
+ continue;
105
+ }
106
+ if let Some(dependency) = manifest.nodes.get(dependency_id) {
107
+ let dependency_hash = hash_node_columns_transitive(manifest, dependency, visited);
108
+ parts.push(format!("node:{}", dependency_hash));
109
+ } else if let Some(source) = manifest.sources.get(dependency_id) {
110
+ let mut columns = source.columns.keys().collect::<Vec<_>>();
111
+ columns.sort_unstable();
112
+ for column in columns {
113
+ parts.push(column.clone());
114
+ }
115
+ if let Some(database) = &source.database {
116
+ parts.push(format!("db:{}", database));
117
+ }
118
+ if let Some(schema) = &source.schema {
119
+ parts.push(format!("schema:{}", schema));
120
+ }
121
+ if let Some(identifier) = &source.identifier {
122
+ parts.push(format!("id:{}", identifier));
123
+ }
124
+ }
125
+ }
126
+
127
+ hash_str(&parts.join("\0"))
128
+ }
129
+
130
+ #[cfg(test)]
131
+ mod tests {
132
+ use std::collections::HashMap;
133
+
134
+ use super::*;
135
+ use crate::parser::manifest::{DependsOn, ManifestColumn, ManifestConfig};
136
+
137
+ fn node(
138
+ unique_id: &str,
139
+ name: &str,
140
+ compiled_code: Option<&str>,
141
+ columns: &[&str],
142
+ dependencies: &[&str],
143
+ ) -> ManifestNode {
144
+ let columns = columns
145
+ .iter()
146
+ .map(|name| {
147
+ (
148
+ (*name).to_string(),
149
+ ManifestColumn {
150
+ name: (*name).to_string(),
151
+ },
152
+ )
153
+ })
154
+ .collect();
155
+ ManifestNode {
156
+ unique_id: unique_id.to_string(),
157
+ name: name.to_string(),
158
+ resource_type: "model".to_string(),
159
+ depends_on: DependsOn {
160
+ nodes: dependencies.iter().map(|id| (*id).to_string()).collect(),
161
+ },
162
+ config: ManifestConfig::default(),
163
+ description: None,
164
+ path: None,
165
+ original_file_path: None,
166
+ columns,
167
+ compiled_code: compiled_code.map(str::to_string),
168
+ database: None,
169
+ schema: None,
170
+ }
171
+ }
172
+
173
+ fn manifest(nodes: Vec<ManifestNode>) -> Manifest {
174
+ Manifest {
175
+ nodes: nodes
176
+ .into_iter()
177
+ .map(|node| (node.unique_id.clone(), node))
178
+ .collect::<HashMap<_, _>>(),
179
+ ..Manifest::default()
180
+ }
181
+ }
182
+
183
+ #[test]
184
+ fn yaml_map_order_does_not_change_proven_ordinal_schema() {
185
+ let upstream_id = "model.test.upstream";
186
+ let downstream_id = "model.test.downstream";
187
+ let upstream_sql = Some("SELECT first_col, second_col FROM source_table");
188
+ let downstream = node(
189
+ downstream_id,
190
+ "downstream",
191
+ Some("SELECT first_col FROM upstream"),
192
+ &[],
193
+ &[upstream_id],
194
+ );
195
+
196
+ let first = build_proven_ordered_schema(
197
+ &manifest(vec![
198
+ node(
199
+ upstream_id,
200
+ "upstream",
201
+ upstream_sql,
202
+ &["first_col", "second_col"],
203
+ &[],
204
+ ),
205
+ node(
206
+ downstream_id,
207
+ "downstream",
208
+ Some("SELECT first_col FROM upstream"),
209
+ &[],
210
+ &[upstream_id],
211
+ ),
212
+ ]),
213
+ &downstream,
214
+ DialectType::Generic,
215
+ )
216
+ .unwrap();
217
+ assert_eq!(
218
+ first.column_names("upstream").unwrap(),
219
+ vec!["first_col", "second_col"]
220
+ );
221
+ // The second manifest has the same SQL but a different YAML map order.
222
+ // Rebuild the node reference from that manifest so only the SQL proof
223
+ // participates in the schema.
224
+ let second_manifest = manifest(vec![
225
+ node(
226
+ upstream_id,
227
+ "upstream",
228
+ upstream_sql,
229
+ &["second_col", "first_col"],
230
+ &[],
231
+ ),
232
+ node(
233
+ downstream_id,
234
+ "downstream",
235
+ Some("SELECT first_col FROM upstream"),
236
+ &[],
237
+ &[upstream_id],
238
+ ),
239
+ ]);
240
+ let second = build_proven_ordered_schema(
241
+ &second_manifest,
242
+ second_manifest.nodes.get(downstream_id).unwrap(),
243
+ DialectType::Generic,
244
+ )
245
+ .unwrap();
246
+ assert_eq!(
247
+ second.column_names("upstream").unwrap(),
248
+ first.column_names("upstream").unwrap()
249
+ );
250
+ }
251
+
252
+ #[test]
253
+ fn only_proven_compiled_named_outputs_enter_the_schema() {
254
+ let good_id = "model.test.good";
255
+ let unnamed_id = "model.test.unnamed";
256
+ let star_id = "model.test.star";
257
+ let downstream = node(
258
+ "model.test.downstream",
259
+ "downstream",
260
+ Some("SELECT value FROM good"),
261
+ &[],
262
+ &[good_id, unnamed_id, star_id],
263
+ );
264
+ let manifest = manifest(vec![
265
+ node(
266
+ good_id,
267
+ "good",
268
+ Some("SELECT first_col, second_col FROM t"),
269
+ &[],
270
+ &[],
271
+ ),
272
+ node(
273
+ unnamed_id,
274
+ "unnamed",
275
+ Some("SELECT value * 2 FROM t"),
276
+ &["yaml_name"],
277
+ &[],
278
+ ),
279
+ node(
280
+ star_id,
281
+ "star",
282
+ Some("SELECT * FROM unknown"),
283
+ &["yaml_name"],
284
+ &[],
285
+ ),
286
+ downstream,
287
+ ]);
288
+
289
+ let schema = build_proven_ordered_schema(
290
+ &manifest,
291
+ manifest.nodes.get("model.test.downstream").unwrap(),
292
+ DialectType::Generic,
293
+ )
294
+ .unwrap();
295
+ assert_eq!(
296
+ schema.column_names("good").unwrap(),
297
+ vec!["first_col", "second_col"]
298
+ );
299
+ assert!(schema.column_names("unnamed").is_err());
300
+ assert!(schema.column_names("star").is_err());
301
+ }
302
+ }
@@ -1,7 +1,7 @@
1
1
  use std::collections::HashSet;
2
2
  use std::path::Path;
3
3
 
4
- use polyglot_sql::DialectType;
4
+ use polyglot_sql::{ColumnResolutionReason, DialectType, Error};
5
5
  use rayon::prelude::*;
6
6
 
7
7
  use crate::parser::manifest::Manifest;
@@ -9,7 +9,9 @@ use crate::parser::manifest::Manifest;
9
9
  mod cache;
10
10
  mod cross_model;
11
11
  mod impact;
12
+ pub mod manifest_schema;
12
13
  mod schema;
14
+ pub mod semantic_model;
13
15
  mod single_model;
14
16
  mod star_guard;
15
17
  #[cfg(test)]
@@ -24,7 +26,8 @@ pub use impact::{
24
26
  ColumnImpactReport, ImpactedColumn, compute_column_impact,
25
27
  compute_column_impact_with_manifest_path,
26
28
  };
27
- use schema::{build_yaml_schema_for_node, compute_manifest_columns_hash, infer_output_columns};
29
+ use manifest_schema::compute_manifest_columns_hash;
30
+ use schema::{build_yaml_schema_for_node, infer_output_columns};
28
31
  use single_model::{prepare_lineage_context_with_expr, run_column_lineage};
29
32
  use star_guard::has_unresolved_stars;
30
33
  pub use types::{
@@ -176,14 +179,19 @@ pub fn compute_column_lineage_with_manifest_path(
176
179
  sources: result.sources,
177
180
  }),
178
181
  Err(e) => {
179
- let hint = (has_star_columns && e.contains("Cannot find column")).then(|| {
180
- "column may be introduced via SELECT * that could not be expanded; \
182
+ let hint =
183
+ (has_star_columns && is_indeterminate_column_resolution(&e)).then(|| {
184
+ "column may be introduced via SELECT * that could not be expanded; \
181
185
  define upstream columns in the model YAML to enable full resolution"
182
- .to_string()
183
- });
186
+ .to_string()
187
+ });
184
188
  Err(ColumnLineageError {
185
189
  kind: ColumnLineageErrorKind::ColumnNotFound,
186
- what: format!("column '{}': {}", col_name, e),
190
+ what: format!(
191
+ "column '{}': {}",
192
+ col_name,
193
+ single_model::format_lineage_error(&e)
194
+ ),
187
195
  why: None,
188
196
  hint,
189
197
  })
@@ -220,6 +228,16 @@ pub fn compute_column_lineage_with_manifest_path(
220
228
  result
221
229
  }
222
230
 
231
+ fn is_indeterminate_column_resolution(error: &Error) -> bool {
232
+ matches!(
233
+ error,
234
+ Error::ColumnResolution {
235
+ reason: ColumnResolutionReason::Indeterminate,
236
+ ..
237
+ }
238
+ )
239
+ }
240
+
223
241
  pub(super) fn find_model_by_name<'a>(
224
242
  manifest: &'a Manifest,
225
243
  name: &str,
@@ -2,16 +2,9 @@ use std::collections::HashSet;
2
2
 
3
3
  use polyglot_sql::{DialectType, Expression, Schema};
4
4
 
5
- use crate::parser::cache::hash_str;
6
5
  use crate::parser::manifest::Manifest;
7
6
 
8
- fn make_fq_table_name(database: Option<&str>, schema: Option<&str>, name: &str) -> String {
9
- match (database, schema) {
10
- (Some(db), Some(s)) => format!("{}.{}.{}", db, s, name),
11
- (None, Some(s)) => format!("{}.{}", s, name),
12
- _ => name.to_string(),
13
- }
14
- }
7
+ use super::manifest_schema::make_fq_table_name;
15
8
 
16
9
  pub(super) fn build_schema_from_manifest(
17
10
  manifest: &Manifest,
@@ -190,60 +183,3 @@ pub(super) fn infer_output_columns(
190
183
  schema.map(|s| s as &dyn polyglot_sql::Schema),
191
184
  )
192
185
  }
193
-
194
- pub(super) fn compute_manifest_columns_hash(
195
- manifest: &Manifest,
196
- node: &crate::parser::manifest::ManifestNode,
197
- ) -> u64 {
198
- let mut visited: HashSet<String> = HashSet::new();
199
- hash_node_columns_transitive(manifest, node, &mut visited)
200
- }
201
-
202
- fn hash_node_columns_transitive(
203
- manifest: &Manifest,
204
- node: &crate::parser::manifest::ManifestNode,
205
- visited: &mut HashSet<String>,
206
- ) -> u64 {
207
- let mut parts: Vec<String> = Vec::new();
208
-
209
- let mut own_cols: Vec<&String> = node.columns.keys().collect();
210
- own_cols.sort();
211
- for col in own_cols {
212
- parts.push(col.clone());
213
- }
214
- if let Some(code) = &node.compiled_code {
215
- parts.push(format!("sql:{}", hash_str(code)));
216
- }
217
- parts.push("|".to_string());
218
-
219
- let mut dep_ids: Vec<&String> = node.depends_on.nodes.iter().collect();
220
- dep_ids.sort();
221
- for dep_id in dep_ids {
222
- parts.push(dep_id.clone());
223
- if visited.contains(dep_id) {
224
- continue;
225
- }
226
- visited.insert(dep_id.clone());
227
- if let Some(dep_node) = manifest.nodes.get(dep_id) {
228
- let dep_hash = hash_node_columns_transitive(manifest, dep_node, visited);
229
- parts.push(format!("node:{}", dep_hash));
230
- } else if let Some(dep_source) = manifest.sources.get(dep_id) {
231
- let mut cols: Vec<&String> = dep_source.columns.keys().collect();
232
- cols.sort();
233
- for col in cols {
234
- parts.push(col.clone());
235
- }
236
- if let Some(db) = &dep_source.database {
237
- parts.push(format!("db:{}", db));
238
- }
239
- if let Some(s) = &dep_source.schema {
240
- parts.push(format!("schema:{}", s));
241
- }
242
- if let Some(id) = &dep_source.identifier {
243
- parts.push(format!("id:{}", id));
244
- }
245
- }
246
- }
247
-
248
- hash_str(&parts.join("\0"))
249
- }