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.
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/Cargo.lock +6 -6
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/Cargo.toml +3 -3
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/PKG-INFO +1 -1
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/cross_model.rs +1 -8
- dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/manifest_schema.rs +302 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/mod.rs +25 -7
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/schema.rs +1 -65
- dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/semantic_model.rs +377 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/single_model.rs +71 -13
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +1 -1
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_star.rs +25 -0
- dlin_cli-0.2.4rc2/crates/dlin-core/src/graph/column_lineage/tests/core_util.rs +137 -0
- dlin_cli-0.2.4rc1/crates/dlin-core/src/graph/column_lineage/tests/core_util.rs +0 -33
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/LICENSE +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/README.md +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/Cargo.toml +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/README.md +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/cli.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/main.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/src/mcp.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin/tests/integration_test.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/Cargo.toml +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/README.md +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/error.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/build_graph.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/generic_tests.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/ref_parsing.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/builder/tests/versioned.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/cache.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/impact.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/star_guard.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_basic.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/core_cross_model.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/impact.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/types.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/collapse.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/filter_graph.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/output.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/search.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/selector.rs +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/transitive.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/filter/tests/versioned.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/impact.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/types.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/input.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/lib.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/cache.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/columns.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/discovery.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/jinja.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/manifest.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/manifest_cache.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/project.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/sql.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/parser/yaml_schema.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/ascii.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/column_graph.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/dot.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/html.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/impact.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/json.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/layout.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/list.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/mermaid.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/mod.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/plain.rs +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/summary.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/render/svg.rs +0 -0
- {dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/tests/column_lineage_test.rs +0 -0
- {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.
|
|
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.
|
|
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.
|
|
600
|
+
version = "0.8.0"
|
|
601
601
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
602
|
-
checksum = "
|
|
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.
|
|
613
|
+
version = "0.8.0"
|
|
614
614
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
615
|
-
checksum = "
|
|
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.
|
|
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.
|
|
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.
|
|
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)'] }
|
{dlin_cli-0.2.4rc1 → dlin_cli-0.2.4rc2}/crates/dlin-core/src/graph/column_lineage/cross_model.rs
RENAMED
|
@@ -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
|
|
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 =
|
|
180
|
-
|
|
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
|
-
|
|
183
|
-
|
|
186
|
+
.to_string()
|
|
187
|
+
});
|
|
184
188
|
Err(ColumnLineageError {
|
|
185
189
|
kind: ColumnLineageErrorKind::ColumnNotFound,
|
|
186
|
-
what: format!(
|
|
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
|
-
|
|
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
|
-
}
|