dlin-cli 0.2.4rc3__tar.gz → 0.2.5__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.4rc3 → dlin_cli-0.2.5}/Cargo.lock +9 -7
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/Cargo.toml +2 -2
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/PKG-INFO +20 -11
- {dlin_cli-0.2.4rc3/crates/dlin → dlin_cli-0.2.5}/README.md +19 -10
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin/Cargo.toml +1 -0
- {dlin_cli-0.2.4rc3/crates/dlin-core → dlin_cli-0.2.5/crates/dlin}/README.md +19 -10
- dlin_cli-0.2.5/crates/dlin/src/cli/column.rs +240 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/command.rs +247 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/common.rs +126 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/graph.rs +309 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/misc.rs +163 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/mod.rs +13 -0
- dlin_cli-0.2.5/crates/dlin/src/cli/summary.rs +321 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/column.rs +315 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/debug.rs +143 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/graph.rs +529 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/manifest.rs +383 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/mod.rs +13 -0
- dlin_cli-0.2.5/crates/dlin/src/commands/shared.rs +331 -0
- dlin_cli-0.2.5/crates/dlin/src/main.rs +129 -0
- dlin_cli-0.2.5/crates/dlin/src/mcp/mod.rs +7 -0
- dlin_cli-0.2.5/crates/dlin/src/mcp/protocol.rs +227 -0
- dlin_cli-0.2.5/crates/dlin/src/mcp/tests.rs +824 -0
- dlin_cli-0.2.5/crates/dlin/src/mcp/tools.rs +529 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/artifacts.rs +47 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/cli.rs +682 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/error_format.rs +93 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/freshness.rs +359 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/generic_test_metadata.rs +654 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/manifest_only.rs +686 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/manifest_only_rest.rs +590 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/parsing.rs +65 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration/sql_mode_test_warning.rs +154 -0
- dlin_cli-0.2.5/crates/dlin/tests/integration_test.rs +80 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/Cargo.toml +1 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5/crates/dlin-core}/README.md +19 -10
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/error.rs +15 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/builder/mod.rs +49 -440
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/project_yaml.rs +194 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/semantic_layer.rs +200 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/tests/build_graph/basic.rs +552 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/tests/build_graph/mod.rs +6 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/tests/build_graph/semantic_layer.rs +228 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/builder/tests/build_graph/yaml_snapshots.rs +428 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/builder/tests/versioned.rs +4 -4
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/mod.rs +0 -8
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/sqllineage.rs +20 -16
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/cache.rs +171 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/cross_model.rs +88 -55
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/impact.rs +24 -42
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/mod.rs +137 -47
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/schema.rs +154 -53
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/backend_regression/basic.rs +226 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/backend_regression/discovery.rs +424 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/backend_regression/mod.rs +324 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/backend_regression/set_operations.rs +575 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +618 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/core_cross_model/mod.rs +580 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/core_cross_model/scenarios.rs +701 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/core_star.rs +2 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/core_util.rs +21 -26
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/tests/impact.rs → dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/impact/core.rs +22 -241
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/impact/edge_cases.rs +117 -0
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/tests/impact/mod.rs +188 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/regression_fixtures.rs +18 -3
- dlin_cli-0.2.5/crates/dlin-core/src/graph/column_lineage/types.rs +390 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/mod.rs +62 -33
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/filter_graph.rs +120 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/selector.rs +44 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/types.rs +6 -3
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/input.rs +86 -10
- dlin_cli-0.2.5/crates/dlin-core/src/parser/cache.rs +790 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/parser/discovery.rs +97 -15
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/mod.rs +141 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/reachability/analysis.rs +67 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/reachability/catalog.rs +131 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/reachability/mod.rs +318 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/reachability/tests.rs +210 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/render.rs +704 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/source.rs +305 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/jinja/tests.rs +1036 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/graph.rs +480 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/mod.rs +454 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/report/decode.rs +493 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/report/mod.rs +571 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/report/tests.rs +562 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/compatibility.rs +366 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/contents.rs +255 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/graph.rs +785 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/identifiers.rs +95 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/mod.rs +8 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest/tests/semantic_layer.rs +141 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/manifest_cache.rs +307 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/parser/mod.rs +1 -1
- dlin_cli-0.2.5/crates/dlin-core/src/parser/project.rs +753 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/sql/mod.rs +334 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/sql/recovery.rs +246 -0
- dlin_cli-0.2.5/crates/dlin-core/src/parser/sql/tests.rs +1078 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/column_graph.rs +2 -491
- dlin_cli-0.2.5/crates/dlin-core/src/render/column_graph_tests.rs +489 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/tests/column_lineage_test.rs +29 -61
- dlin_cli-0.2.4rc3/crates/dlin/src/cli.rs +0 -2429
- dlin_cli-0.2.4rc3/crates/dlin/src/main.rs +0 -1736
- dlin_cli-0.2.4rc3/crates/dlin/src/mcp.rs +0 -1454
- dlin_cli-0.2.4rc3/crates/dlin/tests/integration_test.rs +0 -2812
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/builder/tests/build_graph.rs +0 -1077
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/cache.rs +0 -305
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/tests/backend_regression.rs +0 -1329
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +0 -546
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/tests/core_cross_model.rs +0 -282
- dlin_cli-0.2.4rc3/crates/dlin-core/src/graph/column_lineage/types.rs +0 -174
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/cache.rs +0 -497
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/jinja.rs +0 -753
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/manifest.rs +0 -1879
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/manifest_cache.rs +0 -207
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/project.rs +0 -228
- dlin_cli-0.2.4rc3/crates/dlin-core/src/parser/sql.rs +0 -829
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/LICENSE +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/builder/tests/generic_tests.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/builder/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/builder/tests/ref_parsing.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/catalog.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/catalog_provider.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/dialect.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/backend/types.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/relation.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/alias.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/core_basic.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/core_star_chain.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/collapse.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/mod.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/output.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/search.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/snapshots/dlin_core__graph__filter__tests__collapse__collapse_snapshot.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/transitive.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/filter/tests/versioned.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/impact.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/graph/mod.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/lib.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/parser/columns.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/parser/yaml_schema.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/ascii.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/dot.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/html.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/impact.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/json.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/layout.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/list.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/mermaid.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/mod.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/plain.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_all_transformation_types.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_escapes_special_chars.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_id_collision_avoided.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_indirect.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_single.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_single_model.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_via_path.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid_indirect_edge_label.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_multi_hop.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_non_direct_intermediate.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_dotted_table_name.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_id_collision_avoided.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_label_escaping.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_single_model.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/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.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_no_sources.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_single_model.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_all_edge_types.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_transitive_edges.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__html__tests__snapshot_html_json.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json_with_sql.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text_with_sql.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_json_with_sql.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_node_metadata.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_json.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_plain.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__mixed_direct_and_transitive_edges.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_escapes_quotes.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_lineage.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_single_model.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_collapse.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_grouping.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__transitive_edge_rendering.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__plain__tests__snapshot_plain.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_json.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_text.snap +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/summary.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/crates/dlin-core/src/render/svg.rs +0 -0
- {dlin_cli-0.2.4rc3 → dlin_cli-0.2.5}/pyproject.toml +0 -0
|
@@ -230,12 +230,13 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
|
230
230
|
|
|
231
231
|
[[package]]
|
|
232
232
|
name = "dlin"
|
|
233
|
-
version = "0.2.
|
|
233
|
+
version = "0.2.5"
|
|
234
234
|
dependencies = [
|
|
235
235
|
"anyhow",
|
|
236
236
|
"clap",
|
|
237
237
|
"dlin-core",
|
|
238
238
|
"filetime",
|
|
239
|
+
"insta",
|
|
239
240
|
"libc",
|
|
240
241
|
"path-slash",
|
|
241
242
|
"regex",
|
|
@@ -247,11 +248,12 @@ dependencies = [
|
|
|
247
248
|
|
|
248
249
|
[[package]]
|
|
249
250
|
name = "dlin-core"
|
|
250
|
-
version = "0.2.
|
|
251
|
+
version = "0.2.5"
|
|
251
252
|
dependencies = [
|
|
252
253
|
"anyhow",
|
|
253
254
|
"clap",
|
|
254
255
|
"colored",
|
|
256
|
+
"filetime",
|
|
255
257
|
"globset",
|
|
256
258
|
"indexmap",
|
|
257
259
|
"insta",
|
|
@@ -413,9 +415,9 @@ dependencies = [
|
|
|
413
415
|
|
|
414
416
|
[[package]]
|
|
415
417
|
name = "granit-parser"
|
|
416
|
-
version = "1.0
|
|
418
|
+
version = "1.1.0"
|
|
417
419
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
418
|
-
checksum = "
|
|
420
|
+
checksum = "4ccd1be9ebf2bd5520dbfcfb72b70ef492f654061299a097056f3e73410e38ec"
|
|
419
421
|
dependencies = [
|
|
420
422
|
"arraydeque",
|
|
421
423
|
"smallvec",
|
|
@@ -761,9 +763,9 @@ dependencies = [
|
|
|
761
763
|
|
|
762
764
|
[[package]]
|
|
763
765
|
name = "serde-saphyr"
|
|
764
|
-
version = "1.0
|
|
766
|
+
version = "1.1.0"
|
|
765
767
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
766
|
-
checksum = "
|
|
768
|
+
checksum = "a1ec1f5cac0eb96063c64b28705255a7ed6e7d77f95c1d25e9f8b8c928006ce1"
|
|
767
769
|
dependencies = [
|
|
768
770
|
"annotate-snippets",
|
|
769
771
|
"base64",
|
|
@@ -861,7 +863,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
|
861
863
|
[[package]]
|
|
862
864
|
name = "sqllineage"
|
|
863
865
|
version = "0.2.0"
|
|
864
|
-
source = "git+https://github.com/funcpp/sqllineage.git?rev=
|
|
866
|
+
source = "git+https://github.com/funcpp/sqllineage.git?rev=b010d8083c60aee977055ea36f8a6807c1d51c62#b010d8083c60aee977055ea36f8a6807c1d51c62"
|
|
865
867
|
dependencies = [
|
|
866
868
|
"serde",
|
|
867
869
|
"serde_json",
|
|
@@ -3,7 +3,7 @@ members = ["crates/*"]
|
|
|
3
3
|
resolver = "3"
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.2.
|
|
6
|
+
version = "0.2.5"
|
|
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
|
-
sqllineage = { git = "https://github.com/funcpp/sqllineage.git", rev = "
|
|
26
|
+
sqllineage = { git = "https://github.com/funcpp/sqllineage.git", rev = "b010d8083c60aee977055ea36f8a6807c1d51c62", default-features = false }
|
|
27
27
|
# Must stay in lockstep with the sqlparser version sqllineage depends on; see
|
|
28
28
|
# `sqlparser_version_matches_sqllineage` in dlin-core.
|
|
29
29
|
sqlparser = { version = "0.62", features = ["serde", "visitor"] }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dlin-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -30,7 +30,7 @@ dbt model lineage CLI. Parses SQL files directly or reads a compiled `manifest.j
|
|
|
30
30
|
|
|
31
31
|
Works for developers navigating live SQL files, analysts exploring a shared manifest, AI agents via CLI prompt or MCP server, and CI pipelines.
|
|
32
32
|
|
|
33
|
-
Column-level lineage (`dlin column upstream` / `dlin column downstream`)
|
|
33
|
+
Column-level lineage (`dlin column upstream` / `dlin column downstream`) requires a compiled `manifest.json` and is usable in practice while remaining Experimental for coverage reasons.
|
|
34
34
|
|
|
35
35
|
## Motivation
|
|
36
36
|
|
|
@@ -40,7 +40,7 @@ dlin is designed to fill that gap: a CLI tool that lets AI agents understand a d
|
|
|
40
40
|
|
|
41
41
|
To replace `grep`, speed and size matter. dlin is a small, self-contained binary with no runtime dependencies. It parses SQL directly, evaluates common Jinja patterns without Python, parallelizes file I/O, and caches aggressively.
|
|
42
42
|
|
|
43
|
-
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage
|
|
43
|
+
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage fast and provides column-level lineage for deeper analysis.
|
|
44
44
|
|
|
45
45
|
## Install
|
|
46
46
|
|
|
@@ -94,9 +94,9 @@ git diff --name-only main | dlin graph -o json
|
|
|
94
94
|
|
|
95
95
|
dlin supports two source modes for model-level commands.
|
|
96
96
|
|
|
97
|
-
**SQL parse mode (default)** is for developers
|
|
97
|
+
**SQL parse mode (default)** is for developers editing a live dbt project. It reads `ref()` and `source()` directly from SQL without waiting for `dbt compile`, so model-level lineage quickly identifies the related models. Read the relevant SQL for exact transformation behavior.
|
|
98
98
|
|
|
99
|
-
**Manifest mode** (`--source manifest`) is for analysts or agents
|
|
99
|
+
**Manifest mode** (`--source manifest`) is for analysts or agents analyzing compiled state rather than editing live SQL. A developer compiles once and shares `manifest.json`; users explore the resolved graph without SQL or Python. Use column-level lineage when a field-level trace is needed; it requires the compiled manifest.
|
|
100
100
|
|
|
101
101
|
```sh
|
|
102
102
|
# SQL parse mode: reads SQL files directly (default)
|
|
@@ -111,7 +111,7 @@ For model-name inputs, `manifest.json` is the only file needed in manifest mode.
|
|
|
111
111
|
|
|
112
112
|
### Limitations of SQL parse mode
|
|
113
113
|
|
|
114
|
-
- `var()` resolves from `dbt_project.yml`
|
|
114
|
+
- `var()` resolves from `vars.yml` or `dbt_project.yml` (`--vars` CLI overrides not supported)
|
|
115
115
|
- Runtime context (`target.type`, `env_var()`) is not evaluated
|
|
116
116
|
- Conditional Jinja branches use default values; non-default paths may be missed
|
|
117
117
|
- Generic test IDs are dlin-specific (e.g. `test.not_null.orders.order_id`) and do not match dbt's naming; use manifest mode when exact test IDs matter
|
|
@@ -168,7 +168,7 @@ Pass `--dialect` to match your project's SQL dialect for accurate column lineage
|
|
|
168
168
|
- **Impact analysis with severity**: `dlin impact` scores downstream nodes and flags exposure reachability
|
|
169
169
|
- **Composable**: stdin accepts model names or file paths; pipe with `jq`, `dlin list`, `git diff`, etc.
|
|
170
170
|
- **Agent-friendly**: `--error-format json` emits structured `{"level","what","why","hint"}` on stderr; `--help` is designed for tool discovery
|
|
171
|
-
- **Column-level lineage** (experimental): traces columns across models with transformation classification; requires `manifest.json`
|
|
171
|
+
- **Column-level lineage** (experimental): traces columns across models with transformation classification through the Rust lineage backend; requires `manifest.json`
|
|
172
172
|
|
|
173
173
|
## Mermaid diagrams
|
|
174
174
|
|
|
@@ -304,10 +304,7 @@ Output formats: ASCII (default), JSON, Mermaid, Graphviz DOT, Plain, SVG, HTML.
|
|
|
304
304
|
|
|
305
305
|
## Column-level lineage (Experimental)
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
> Column-level lineage uses [sqllineage](https://github.com/funcpp/sqllineage) for SQL parsing and lineage extraction. The production backend directly supports Generic, PostgreSQL, MySQL, Hive, Databricks, Snowflake, BigQuery, DuckDB, SQLite, Spark, Trino, Redshift, T-SQL, and ClickHouse. The `dlin` CLI and MCP resolve other recognized dialects to Generic with a warning; direct `dlin-core` API callers receive an unsupported-dialect error instead. Coverage still varies by SQL complexity and dialect, and patterns such as `SELECT *` chains, STRUCT expansion, and some database-specific syntax may remain unresolved.
|
|
309
|
-
|
|
310
|
-
`dlin column upstream` and `dlin column downstream` trace columns across models. Unlike model-level commands, they always require a compiled `manifest.json`. Run `dbt compile` first.
|
|
307
|
+
`dlin column upstream` and `dlin column downstream` trace columns across models. They require a compiled `manifest.json`, so run `dbt compile` first. Regression fixtures and real dbt project validation show that column-level lineage is usable in practice. Experimental reflects the Rust stack's shorter production history and remaining cross-dialect and complex-SQL coverage gaps, not a prototype-only status.
|
|
311
308
|
|
|
312
309
|
```sh
|
|
313
310
|
# Where does each output column of orders come from?
|
|
@@ -424,6 +421,18 @@ flowchart LR
|
|
|
424
421
|
|
|
425
422
|
`stg_orders.order_id` flows directly into `orders.order_id` and `order_enriched.order_id`. `orders.order_id` is then aggregated into `customers.order_count`. Each edge shows its per-hop transformation type.
|
|
426
423
|
|
|
424
|
+
### Performance benchmark
|
|
425
|
+
|
|
426
|
+
Correctness-gated means from the synthetic scalability run (3 runs, 1 warmup):
|
|
427
|
+
|
|
428
|
+
| Workload | dlin 0.2.4 | [Parrant 0.17.2](https://pypi.org/project/parrant/0.17.2/) | [dbt-meta 0.3.8](https://pypi.org/project/dbt-meta/0.3.8/) |
|
|
429
|
+
| --- | ---: | ---: | ---: |
|
|
430
|
+
| Volume, 100,150 columns, single upstream | 88.9 ms | 37.4 s | build >120 s timeout; query not run |
|
|
431
|
+
| Deep 64, single upstream | 115 ms | 1.42 s | build 4.86 s; query 411 ms |
|
|
432
|
+
| Fan-out 128, downstream | 114 ms | 1.78 s | build 6.47 s; query 363 ms |
|
|
433
|
+
|
|
434
|
+
These synthetic results use artifacts derived from the real dbt fixture. Native Rust avoids Python startup and dlin showed lower latency here; dlin uses `--no-cache`, Parrant includes parsing, and dbt-meta query excludes build. They are not a general ranking; see the [full results and reproduction](benchmarks/column-lineage/results/published/scalability/summary.md).
|
|
435
|
+
|
|
427
436
|
### Known limitations
|
|
428
437
|
|
|
429
438
|
- **Requires `dbt compile`**: no SQL parse mode fallback; manifest with compiled SQL is always needed
|
|
@@ -8,7 +8,7 @@ dbt model lineage CLI. Parses SQL files directly or reads a compiled `manifest.j
|
|
|
8
8
|
|
|
9
9
|
Works for developers navigating live SQL files, analysts exploring a shared manifest, AI agents via CLI prompt or MCP server, and CI pipelines.
|
|
10
10
|
|
|
11
|
-
Column-level lineage (`dlin column upstream` / `dlin column downstream`)
|
|
11
|
+
Column-level lineage (`dlin column upstream` / `dlin column downstream`) requires a compiled `manifest.json` and is usable in practice while remaining Experimental for coverage reasons.
|
|
12
12
|
|
|
13
13
|
## Motivation
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ dlin is designed to fill that gap: a CLI tool that lets AI agents understand a d
|
|
|
18
18
|
|
|
19
19
|
To replace `grep`, speed and size matter. dlin is a small, self-contained binary with no runtime dependencies. It parses SQL directly, evaluates common Jinja patterns without Python, parallelizes file I/O, and caches aggressively.
|
|
20
20
|
|
|
21
|
-
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage
|
|
21
|
+
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage fast and provides column-level lineage for deeper analysis.
|
|
22
22
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
@@ -72,9 +72,9 @@ git diff --name-only main | dlin graph -o json
|
|
|
72
72
|
|
|
73
73
|
dlin supports two source modes for model-level commands.
|
|
74
74
|
|
|
75
|
-
**SQL parse mode (default)** is for developers
|
|
75
|
+
**SQL parse mode (default)** is for developers editing a live dbt project. It reads `ref()` and `source()` directly from SQL without waiting for `dbt compile`, so model-level lineage quickly identifies the related models. Read the relevant SQL for exact transformation behavior.
|
|
76
76
|
|
|
77
|
-
**Manifest mode** (`--source manifest`) is for analysts or agents
|
|
77
|
+
**Manifest mode** (`--source manifest`) is for analysts or agents analyzing compiled state rather than editing live SQL. A developer compiles once and shares `manifest.json`; users explore the resolved graph without SQL or Python. Use column-level lineage when a field-level trace is needed; it requires the compiled manifest.
|
|
78
78
|
|
|
79
79
|
```sh
|
|
80
80
|
# SQL parse mode: reads SQL files directly (default)
|
|
@@ -89,7 +89,7 @@ For model-name inputs, `manifest.json` is the only file needed in manifest mode.
|
|
|
89
89
|
|
|
90
90
|
### Limitations of SQL parse mode
|
|
91
91
|
|
|
92
|
-
- `var()` resolves from `dbt_project.yml`
|
|
92
|
+
- `var()` resolves from `vars.yml` or `dbt_project.yml` (`--vars` CLI overrides not supported)
|
|
93
93
|
- Runtime context (`target.type`, `env_var()`) is not evaluated
|
|
94
94
|
- Conditional Jinja branches use default values; non-default paths may be missed
|
|
95
95
|
- Generic test IDs are dlin-specific (e.g. `test.not_null.orders.order_id`) and do not match dbt's naming; use manifest mode when exact test IDs matter
|
|
@@ -146,7 +146,7 @@ Pass `--dialect` to match your project's SQL dialect for accurate column lineage
|
|
|
146
146
|
- **Impact analysis with severity**: `dlin impact` scores downstream nodes and flags exposure reachability
|
|
147
147
|
- **Composable**: stdin accepts model names or file paths; pipe with `jq`, `dlin list`, `git diff`, etc.
|
|
148
148
|
- **Agent-friendly**: `--error-format json` emits structured `{"level","what","why","hint"}` on stderr; `--help` is designed for tool discovery
|
|
149
|
-
- **Column-level lineage** (experimental): traces columns across models with transformation classification; requires `manifest.json`
|
|
149
|
+
- **Column-level lineage** (experimental): traces columns across models with transformation classification through the Rust lineage backend; requires `manifest.json`
|
|
150
150
|
|
|
151
151
|
## Mermaid diagrams
|
|
152
152
|
|
|
@@ -282,10 +282,7 @@ Output formats: ASCII (default), JSON, Mermaid, Graphviz DOT, Plain, SVG, HTML.
|
|
|
282
282
|
|
|
283
283
|
## Column-level lineage (Experimental)
|
|
284
284
|
|
|
285
|
-
|
|
286
|
-
> Column-level lineage uses [sqllineage](https://github.com/funcpp/sqllineage) for SQL parsing and lineage extraction. The production backend directly supports Generic, PostgreSQL, MySQL, Hive, Databricks, Snowflake, BigQuery, DuckDB, SQLite, Spark, Trino, Redshift, T-SQL, and ClickHouse. The `dlin` CLI and MCP resolve other recognized dialects to Generic with a warning; direct `dlin-core` API callers receive an unsupported-dialect error instead. Coverage still varies by SQL complexity and dialect, and patterns such as `SELECT *` chains, STRUCT expansion, and some database-specific syntax may remain unresolved.
|
|
287
|
-
|
|
288
|
-
`dlin column upstream` and `dlin column downstream` trace columns across models. Unlike model-level commands, they always require a compiled `manifest.json`. Run `dbt compile` first.
|
|
285
|
+
`dlin column upstream` and `dlin column downstream` trace columns across models. They require a compiled `manifest.json`, so run `dbt compile` first. Regression fixtures and real dbt project validation show that column-level lineage is usable in practice. Experimental reflects the Rust stack's shorter production history and remaining cross-dialect and complex-SQL coverage gaps, not a prototype-only status.
|
|
289
286
|
|
|
290
287
|
```sh
|
|
291
288
|
# Where does each output column of orders come from?
|
|
@@ -402,6 +399,18 @@ flowchart LR
|
|
|
402
399
|
|
|
403
400
|
`stg_orders.order_id` flows directly into `orders.order_id` and `order_enriched.order_id`. `orders.order_id` is then aggregated into `customers.order_count`. Each edge shows its per-hop transformation type.
|
|
404
401
|
|
|
402
|
+
### Performance benchmark
|
|
403
|
+
|
|
404
|
+
Correctness-gated means from the synthetic scalability run (3 runs, 1 warmup):
|
|
405
|
+
|
|
406
|
+
| Workload | dlin 0.2.4 | [Parrant 0.17.2](https://pypi.org/project/parrant/0.17.2/) | [dbt-meta 0.3.8](https://pypi.org/project/dbt-meta/0.3.8/) |
|
|
407
|
+
| --- | ---: | ---: | ---: |
|
|
408
|
+
| Volume, 100,150 columns, single upstream | 88.9 ms | 37.4 s | build >120 s timeout; query not run |
|
|
409
|
+
| Deep 64, single upstream | 115 ms | 1.42 s | build 4.86 s; query 411 ms |
|
|
410
|
+
| Fan-out 128, downstream | 114 ms | 1.78 s | build 6.47 s; query 363 ms |
|
|
411
|
+
|
|
412
|
+
These synthetic results use artifacts derived from the real dbt fixture. Native Rust avoids Python startup and dlin showed lower latency here; dlin uses `--no-cache`, Parrant includes parsing, and dbt-meta query excludes build. They are not a general ranking; see the [full results and reproduction](benchmarks/column-lineage/results/published/scalability/summary.md).
|
|
413
|
+
|
|
405
414
|
### Known limitations
|
|
406
415
|
|
|
407
416
|
- **Requires `dbt compile`**: no SQL parse mode fallback; manifest with compiled SQL is always needed
|
|
@@ -8,7 +8,7 @@ dbt model lineage CLI. Parses SQL files directly or reads a compiled `manifest.j
|
|
|
8
8
|
|
|
9
9
|
Works for developers navigating live SQL files, analysts exploring a shared manifest, AI agents via CLI prompt or MCP server, and CI pipelines.
|
|
10
10
|
|
|
11
|
-
Column-level lineage (`dlin column upstream` / `dlin column downstream`)
|
|
11
|
+
Column-level lineage (`dlin column upstream` / `dlin column downstream`) requires a compiled `manifest.json` and is usable in practice while remaining Experimental for coverage reasons.
|
|
12
12
|
|
|
13
13
|
## Motivation
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ dlin is designed to fill that gap: a CLI tool that lets AI agents understand a d
|
|
|
18
18
|
|
|
19
19
|
To replace `grep`, speed and size matter. dlin is a small, self-contained binary with no runtime dependencies. It parses SQL directly, evaluates common Jinja patterns without Python, parallelizes file I/O, and caches aggressively.
|
|
20
20
|
|
|
21
|
-
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage
|
|
21
|
+
The key idea behind dlin is that finding the right models fast is what matters most. The hard part for agents is knowing which models to look at in the first place. dlin focuses on making model-level lineage fast and provides column-level lineage for deeper analysis.
|
|
22
22
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
@@ -72,9 +72,9 @@ git diff --name-only main | dlin graph -o json
|
|
|
72
72
|
|
|
73
73
|
dlin supports two source modes for model-level commands.
|
|
74
74
|
|
|
75
|
-
**SQL parse mode (default)** is for developers
|
|
75
|
+
**SQL parse mode (default)** is for developers editing a live dbt project. It reads `ref()` and `source()` directly from SQL without waiting for `dbt compile`, so model-level lineage quickly identifies the related models. Read the relevant SQL for exact transformation behavior.
|
|
76
76
|
|
|
77
|
-
**Manifest mode** (`--source manifest`) is for analysts or agents
|
|
77
|
+
**Manifest mode** (`--source manifest`) is for analysts or agents analyzing compiled state rather than editing live SQL. A developer compiles once and shares `manifest.json`; users explore the resolved graph without SQL or Python. Use column-level lineage when a field-level trace is needed; it requires the compiled manifest.
|
|
78
78
|
|
|
79
79
|
```sh
|
|
80
80
|
# SQL parse mode: reads SQL files directly (default)
|
|
@@ -89,7 +89,7 @@ For model-name inputs, `manifest.json` is the only file needed in manifest mode.
|
|
|
89
89
|
|
|
90
90
|
### Limitations of SQL parse mode
|
|
91
91
|
|
|
92
|
-
- `var()` resolves from `dbt_project.yml`
|
|
92
|
+
- `var()` resolves from `vars.yml` or `dbt_project.yml` (`--vars` CLI overrides not supported)
|
|
93
93
|
- Runtime context (`target.type`, `env_var()`) is not evaluated
|
|
94
94
|
- Conditional Jinja branches use default values; non-default paths may be missed
|
|
95
95
|
- Generic test IDs are dlin-specific (e.g. `test.not_null.orders.order_id`) and do not match dbt's naming; use manifest mode when exact test IDs matter
|
|
@@ -146,7 +146,7 @@ Pass `--dialect` to match your project's SQL dialect for accurate column lineage
|
|
|
146
146
|
- **Impact analysis with severity**: `dlin impact` scores downstream nodes and flags exposure reachability
|
|
147
147
|
- **Composable**: stdin accepts model names or file paths; pipe with `jq`, `dlin list`, `git diff`, etc.
|
|
148
148
|
- **Agent-friendly**: `--error-format json` emits structured `{"level","what","why","hint"}` on stderr; `--help` is designed for tool discovery
|
|
149
|
-
- **Column-level lineage** (experimental): traces columns across models with transformation classification; requires `manifest.json`
|
|
149
|
+
- **Column-level lineage** (experimental): traces columns across models with transformation classification through the Rust lineage backend; requires `manifest.json`
|
|
150
150
|
|
|
151
151
|
## Mermaid diagrams
|
|
152
152
|
|
|
@@ -282,10 +282,7 @@ Output formats: ASCII (default), JSON, Mermaid, Graphviz DOT, Plain, SVG, HTML.
|
|
|
282
282
|
|
|
283
283
|
## Column-level lineage (Experimental)
|
|
284
284
|
|
|
285
|
-
|
|
286
|
-
> Column-level lineage uses [sqllineage](https://github.com/funcpp/sqllineage) for SQL parsing and lineage extraction. The production backend directly supports Generic, PostgreSQL, MySQL, Hive, Databricks, Snowflake, BigQuery, DuckDB, SQLite, Spark, Trino, Redshift, T-SQL, and ClickHouse. The `dlin` CLI and MCP resolve other recognized dialects to Generic with a warning; direct `dlin-core` API callers receive an unsupported-dialect error instead. Coverage still varies by SQL complexity and dialect, and patterns such as `SELECT *` chains, STRUCT expansion, and some database-specific syntax may remain unresolved.
|
|
287
|
-
|
|
288
|
-
`dlin column upstream` and `dlin column downstream` trace columns across models. Unlike model-level commands, they always require a compiled `manifest.json`. Run `dbt compile` first.
|
|
285
|
+
`dlin column upstream` and `dlin column downstream` trace columns across models. They require a compiled `manifest.json`, so run `dbt compile` first. Regression fixtures and real dbt project validation show that column-level lineage is usable in practice. Experimental reflects the Rust stack's shorter production history and remaining cross-dialect and complex-SQL coverage gaps, not a prototype-only status.
|
|
289
286
|
|
|
290
287
|
```sh
|
|
291
288
|
# Where does each output column of orders come from?
|
|
@@ -402,6 +399,18 @@ flowchart LR
|
|
|
402
399
|
|
|
403
400
|
`stg_orders.order_id` flows directly into `orders.order_id` and `order_enriched.order_id`. `orders.order_id` is then aggregated into `customers.order_count`. Each edge shows its per-hop transformation type.
|
|
404
401
|
|
|
402
|
+
### Performance benchmark
|
|
403
|
+
|
|
404
|
+
Correctness-gated means from the synthetic scalability run (3 runs, 1 warmup):
|
|
405
|
+
|
|
406
|
+
| Workload | dlin 0.2.4 | [Parrant 0.17.2](https://pypi.org/project/parrant/0.17.2/) | [dbt-meta 0.3.8](https://pypi.org/project/dbt-meta/0.3.8/) |
|
|
407
|
+
| --- | ---: | ---: | ---: |
|
|
408
|
+
| Volume, 100,150 columns, single upstream | 88.9 ms | 37.4 s | build >120 s timeout; query not run |
|
|
409
|
+
| Deep 64, single upstream | 115 ms | 1.42 s | build 4.86 s; query 411 ms |
|
|
410
|
+
| Fan-out 128, downstream | 114 ms | 1.78 s | build 6.47 s; query 363 ms |
|
|
411
|
+
|
|
412
|
+
These synthetic results use artifacts derived from the real dbt fixture. Native Rust avoids Python startup and dlin showed lower latency here; dlin uses `--no-cache`, Parrant includes parsing, and dbt-meta query excludes build. They are not a general ranking; see the [full results and reproduction](benchmarks/column-lineage/results/published/scalability/summary.md).
|
|
413
|
+
|
|
405
414
|
### Known limitations
|
|
406
415
|
|
|
407
416
|
- **Requires `dbt compile`**: no SQL parse mode fallback; manifest with compiled SQL is always needed
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
2
|
+
|
|
3
|
+
use super::*;
|
|
4
|
+
use clap::Subcommand;
|
|
5
|
+
|
|
6
|
+
#[derive(Debug, clap::Args)]
|
|
7
|
+
pub struct ColumnArgs {
|
|
8
|
+
#[command(subcommand)]
|
|
9
|
+
pub command: ColumnCommand,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#[derive(Debug, Subcommand)]
|
|
13
|
+
pub enum ColumnCommand {
|
|
14
|
+
/// Compute column-level lineage for a model (traces upstream sources)
|
|
15
|
+
#[command(
|
|
16
|
+
long_about = "\
|
|
17
|
+
Compute column-level lineage for one or more models.
|
|
18
|
+
|
|
19
|
+
Direction: upstream only. Traces backward from a model's output columns to
|
|
20
|
+
their raw source columns across the full DAG. There are no -u/-d depth flags
|
|
21
|
+
— the entire upstream chain is always traversed automatically.
|
|
22
|
+
|
|
23
|
+
To find what downstream models or columns would be affected by changing a
|
|
24
|
+
specific column, use `dlin column downstream` instead.
|
|
25
|
+
|
|
26
|
+
There is no --source flag; manifest.json is the only data source (unlike
|
|
27
|
+
`dlin graph` which supports both SQL files and manifest).
|
|
28
|
+
|
|
29
|
+
Requires manifest.json with compiled SQL (run `dbt compile` first).
|
|
30
|
+
Use `dlin check-manifest` to verify freshness before querying.
|
|
31
|
+
|
|
32
|
+
Column resolution order:
|
|
33
|
+
1. YAML column definitions (schema.yml / models.yml)
|
|
34
|
+
2. SQL inference from compiled_code (fallback when YAML is absent)
|
|
35
|
+
|
|
36
|
+
Stdin/pipe support:
|
|
37
|
+
Accepts model names or file paths on stdin (one per line).
|
|
38
|
+
File paths (detected by extension or path separator) are resolved to
|
|
39
|
+
model names using the dbt project configuration.
|
|
40
|
+
|
|
41
|
+
Output format (-o/--output):
|
|
42
|
+
json (default) JSON array per model with the following structure:
|
|
43
|
+
model model name
|
|
44
|
+
traced_columns number of columns successfully traced
|
|
45
|
+
total_columns total number of columns attempted
|
|
46
|
+
columns[]
|
|
47
|
+
column output column name
|
|
48
|
+
transformation how the column was derived:
|
|
49
|
+
direct passed through unchanged (including renames)
|
|
50
|
+
aggregation aggregate function (SUM, COUNT, etc.)
|
|
51
|
+
expression arithmetic or other expression
|
|
52
|
+
cast type cast (CAST(x AS INT))
|
|
53
|
+
conditional CASE WHEN expression
|
|
54
|
+
unknown could not classify
|
|
55
|
+
sources[]
|
|
56
|
+
table source model or raw table name; empty string (\"\") when the
|
|
57
|
+
value originates from a literal (NULL, constant, UNNEST, etc.)
|
|
58
|
+
— rendered as \"(literal)\" in plain/mermaid/dot outputs
|
|
59
|
+
column source column name
|
|
60
|
+
model_path[] intermediate [model, column, transformation] triples traversed (omitted if empty)
|
|
61
|
+
errors[] parse or resolution diagnostics. An indeterminate per-column
|
|
62
|
+
diagnostic is non-fatal and does not change the exit code;
|
|
63
|
+
model-level, missing-column, ambiguous, and parse diagnostics
|
|
64
|
+
are fatal (exit code 1).
|
|
65
|
+
plain human-readable text, one model per block
|
|
66
|
+
mermaid Mermaid flowchart (LR) with subgraphs per model
|
|
67
|
+
dot Graphviz DOT format; models as clusters, columns as nodes
|
|
68
|
+
color-coded by transformation type (pipe to `dot -Tsvg`)
|
|
69
|
+
|
|
70
|
+
Exit codes:
|
|
71
|
+
0 Success
|
|
72
|
+
1 Error (model not found, no manifest, fatal analysis errors, etc.)",
|
|
73
|
+
after_long_help = "\
|
|
74
|
+
Examples:
|
|
75
|
+
# Column lineage for a single model (JSON output)
|
|
76
|
+
dlin column upstream orders
|
|
77
|
+
|
|
78
|
+
# Human-readable plain output
|
|
79
|
+
dlin column upstream orders -o plain
|
|
80
|
+
|
|
81
|
+
# Mermaid flowchart
|
|
82
|
+
dlin column upstream orders -o mermaid
|
|
83
|
+
|
|
84
|
+
# Specific columns only
|
|
85
|
+
dlin column upstream orders --column order_id --column status
|
|
86
|
+
|
|
87
|
+
# Multiple models
|
|
88
|
+
dlin column upstream orders stg_orders
|
|
89
|
+
|
|
90
|
+
# With explicit manifest path
|
|
91
|
+
dlin column upstream orders --manifest-path target/manifest.json
|
|
92
|
+
|
|
93
|
+
# BigQuery project
|
|
94
|
+
dlin column upstream orders --dialect bigquery
|
|
95
|
+
|
|
96
|
+
# From git diff (pipe changed files)
|
|
97
|
+
git diff --name-only main | dlin column upstream -o json"
|
|
98
|
+
)]
|
|
99
|
+
Upstream(ColumnGraphArgs),
|
|
100
|
+
|
|
101
|
+
/// Analyze downstream column-level impact of changing a column
|
|
102
|
+
#[command(
|
|
103
|
+
long_about = "\
|
|
104
|
+
Analyze downstream column-level impact of changing a column.
|
|
105
|
+
|
|
106
|
+
Direction: downstream only. Starting from a specific column, follows forward
|
|
107
|
+
edges to find all dependent models and columns. There are no -u/-d depth flags
|
|
108
|
+
— all downstream dependents are always included.
|
|
109
|
+
|
|
110
|
+
This is the reverse direction of `dlin column upstream` (which traces upstream
|
|
111
|
+
sources). To trace where a column's data comes from, use `dlin column upstream`.
|
|
112
|
+
|
|
113
|
+
Takes a single model and one or more --column flags (required).
|
|
114
|
+
|
|
115
|
+
There is no --source flag; manifest.json is the only data source (unlike
|
|
116
|
+
`dlin graph`/`dlin impact` which support both SQL files and manifest).
|
|
117
|
+
|
|
118
|
+
Requires compiled SQL in manifest.json — run `dbt compile` first.
|
|
119
|
+
Use `dlin check-manifest` to verify freshness before querying.
|
|
120
|
+
|
|
121
|
+
Output format (-o/--output):
|
|
122
|
+
json (default) JSON array per column with affected downstream columns and models
|
|
123
|
+
plain human-readable text, one source column per block
|
|
124
|
+
mermaid Mermaid flowchart (LR) showing impacted columns across models
|
|
125
|
+
dot Graphviz DOT format; models as clusters, columns as nodes
|
|
126
|
+
color-coded by transformation type (pipe to `dot -Tsvg`)
|
|
127
|
+
|
|
128
|
+
Exit codes:
|
|
129
|
+
0 Success
|
|
130
|
+
1 Error (model not found, no manifest, fatal analysis errors, etc.)",
|
|
131
|
+
after_long_help = "\
|
|
132
|
+
Examples:
|
|
133
|
+
# Impact of changing a single column (JSON output)
|
|
134
|
+
dlin column downstream stg_orders --column order_id
|
|
135
|
+
|
|
136
|
+
# Human-readable plain output
|
|
137
|
+
dlin column downstream stg_orders --column order_id -o plain
|
|
138
|
+
|
|
139
|
+
# Mermaid flowchart
|
|
140
|
+
dlin column downstream stg_orders --column order_id -o mermaid
|
|
141
|
+
|
|
142
|
+
# Impact of multiple columns
|
|
143
|
+
dlin column downstream stg_orders --column order_id --column status
|
|
144
|
+
|
|
145
|
+
# With explicit manifest path
|
|
146
|
+
dlin column downstream stg_orders --column order_id --manifest-path target/manifest.json
|
|
147
|
+
|
|
148
|
+
# BigQuery project
|
|
149
|
+
dlin column downstream stg_orders --column order_id --dialect bigquery"
|
|
150
|
+
)]
|
|
151
|
+
Downstream(ColumnImpactArgs),
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#[derive(Debug, clap::Args)]
|
|
155
|
+
pub struct ColumnGraphArgs {
|
|
156
|
+
/// Model names or file paths to analyze column lineage for (also accepts stdin)
|
|
157
|
+
pub model: Vec<String>,
|
|
158
|
+
|
|
159
|
+
/// Specific columns to analyze (analyzes all columns if omitted)
|
|
160
|
+
#[arg(long)]
|
|
161
|
+
pub column: Vec<String>,
|
|
162
|
+
|
|
163
|
+
/// Output format: json (default), plain, mermaid
|
|
164
|
+
#[arg(short = 'o', long, default_value = "json")]
|
|
165
|
+
pub output: ColumnOutputFormat,
|
|
166
|
+
|
|
167
|
+
/// SQL dialect for parsing compiled SQL.
|
|
168
|
+
/// Auto-detected from manifest.metadata.adapter_type when omitted. Recognized dialects
|
|
169
|
+
/// removed from the active backend fall back to Generic with a warning.
|
|
170
|
+
#[arg(long, value_parser = parse_dialect_arg)]
|
|
171
|
+
pub dialect: Option<DialectArg>,
|
|
172
|
+
|
|
173
|
+
/// Path to dbt project directory
|
|
174
|
+
#[arg(short = 'p', long = "project-dir", default_value = ".")]
|
|
175
|
+
pub project_dir: PathBuf,
|
|
176
|
+
|
|
177
|
+
/// Path to manifest.json file or directory containing target/manifest.json (default: <project-dir>/target/manifest.json)
|
|
178
|
+
#[arg(long)]
|
|
179
|
+
pub manifest_path: Option<PathBuf>,
|
|
180
|
+
|
|
181
|
+
/// Directory for caching column lineage results (default: <project-dir>/.dlin_cache)
|
|
182
|
+
#[arg(long, env = "DLIN_CACHE_DIR")]
|
|
183
|
+
pub cache_dir: Option<PathBuf>,
|
|
184
|
+
|
|
185
|
+
/// Disable column lineage cache
|
|
186
|
+
#[arg(long, env = "DLIN_NO_CACHE")]
|
|
187
|
+
pub no_cache: bool,
|
|
188
|
+
|
|
189
|
+
/// Discard existing cache and rebuild from scratch
|
|
190
|
+
#[arg(long, env = "DLIN_REFRESH_CACHE", conflicts_with = "no_cache")]
|
|
191
|
+
pub refresh_cache: bool,
|
|
192
|
+
|
|
193
|
+
/// Suppress warning messages
|
|
194
|
+
#[arg(short = 'q', long)]
|
|
195
|
+
pub quiet: bool,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#[derive(Debug, clap::Args)]
|
|
199
|
+
pub struct ColumnImpactArgs {
|
|
200
|
+
/// Model name to analyze column downstream impact for
|
|
201
|
+
pub model: String,
|
|
202
|
+
|
|
203
|
+
/// Columns to analyze impact for (required)
|
|
204
|
+
#[arg(long, required = true)]
|
|
205
|
+
pub column: Vec<String>,
|
|
206
|
+
|
|
207
|
+
/// Output format: json (default), plain, mermaid
|
|
208
|
+
#[arg(short = 'o', long, default_value = "json")]
|
|
209
|
+
pub output: ColumnOutputFormat,
|
|
210
|
+
|
|
211
|
+
/// SQL dialect for parsing compiled SQL.
|
|
212
|
+
/// Auto-detected from manifest.metadata.adapter_type when omitted. Recognized dialects
|
|
213
|
+
/// removed from the active backend fall back to Generic with a warning.
|
|
214
|
+
#[arg(long, value_parser = parse_dialect_arg)]
|
|
215
|
+
pub dialect: Option<DialectArg>,
|
|
216
|
+
|
|
217
|
+
/// Path to dbt project directory
|
|
218
|
+
#[arg(short = 'p', long = "project-dir", default_value = ".")]
|
|
219
|
+
pub project_dir: PathBuf,
|
|
220
|
+
|
|
221
|
+
/// Path to manifest.json file or directory containing target/manifest.json (default: <project-dir>/target/manifest.json)
|
|
222
|
+
#[arg(long)]
|
|
223
|
+
pub manifest_path: Option<PathBuf>,
|
|
224
|
+
|
|
225
|
+
/// Directory for caching column lineage results (default: <project-dir>/.dlin_cache)
|
|
226
|
+
#[arg(long, env = "DLIN_CACHE_DIR")]
|
|
227
|
+
pub cache_dir: Option<PathBuf>,
|
|
228
|
+
|
|
229
|
+
/// Disable column lineage cache
|
|
230
|
+
#[arg(long, env = "DLIN_NO_CACHE")]
|
|
231
|
+
pub no_cache: bool,
|
|
232
|
+
|
|
233
|
+
/// Discard existing cache and rebuild from scratch
|
|
234
|
+
#[arg(long, env = "DLIN_REFRESH_CACHE", conflicts_with = "no_cache")]
|
|
235
|
+
pub refresh_cache: bool,
|
|
236
|
+
|
|
237
|
+
/// Suppress warning messages
|
|
238
|
+
#[arg(short = 'q', long)]
|
|
239
|
+
pub quiet: bool,
|
|
240
|
+
}
|