dlin-cli 0.2.0a1__tar.gz → 0.2.0a2__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.0a1 → dlin_cli-0.2.0a2}/Cargo.lock +2 -2
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/Cargo.toml +2 -2
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/PKG-INFO +1 -1
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin/src/cli.rs +211 -83
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin/src/main.rs +60 -38
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin/tests/integration_test.rs +8 -8
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/single_model.rs +21 -1
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/tests/core.rs +95 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs +149 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/column_graph.rs +621 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/mermaid.rs +10 -26
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/mod.rs +21 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid_indirect_edge_label.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain.snap +6 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_multi_hop.snap +6 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_dotted_table_name.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_id_collision_avoided.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_label_escaping.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_single_model.snap +13 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_no_sources.snap +6 -0
- dlin_cli-0.2.0a2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_single_model.snap +7 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/LICENSE +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/README.md +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin/Cargo.toml +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin/README.md +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/Cargo.toml +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/README.md +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/error.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/builder.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/cache.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/cross_model.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/impact.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/mod.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/schema.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/tests/impact.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/column_lineage/types.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/filter.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/impact.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/mod.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_bfs_pseudoendpoint.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_endpoints_fan_out.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_endpoints_leaf_model.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_multiple_focus_models.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_no_source_exposure.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_preserve_focus.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_node_type_filter.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_select_filter.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_select_with_node_type.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/graph/types.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/input.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/lib.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/cache.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/columns.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/discovery.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/jinja.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/manifest.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/mod.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/project.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/sql.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/parser/yaml_schema.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/ascii.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/dot.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/html.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/impact.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/json.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/layout.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/list.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/plain.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_all_edge_types.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_transitive_edges.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__html__tests__snapshot_html_json.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json_with_sql.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text_with_sql.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_json_with_sql.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_node_metadata.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_json.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_plain.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__mixed_direct_and_transitive_edges.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_escapes_quotes.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_lineage.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_single_model.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_collapse.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_grouping.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__transitive_edge_rendering.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__plain__tests__snapshot_plain.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_json.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_text.snap +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/summary.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/src/render/svg.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/crates/dlin-core/tests/column_lineage_test.rs +0 -0
- {dlin_cli-0.2.0a1 → dlin_cli-0.2.0a2}/pyproject.toml +0 -0
|
@@ -231,7 +231,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
|
231
231
|
|
|
232
232
|
[[package]]
|
|
233
233
|
name = "dlin"
|
|
234
|
-
version = "0.2.0-alpha.
|
|
234
|
+
version = "0.2.0-alpha.2"
|
|
235
235
|
dependencies = [
|
|
236
236
|
"anyhow",
|
|
237
237
|
"clap",
|
|
@@ -247,7 +247,7 @@ dependencies = [
|
|
|
247
247
|
|
|
248
248
|
[[package]]
|
|
249
249
|
name = "dlin-core"
|
|
250
|
-
version = "0.2.0-alpha.
|
|
250
|
+
version = "0.2.0-alpha.2"
|
|
251
251
|
dependencies = [
|
|
252
252
|
"anyhow",
|
|
253
253
|
"clap",
|
|
@@ -3,7 +3,7 @@ members = ["crates/*"]
|
|
|
3
3
|
resolver = "3"
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.2.0-alpha.
|
|
6
|
+
version = "0.2.0-alpha.2"
|
|
7
7
|
edition = "2024"
|
|
8
8
|
license = "MIT"
|
|
9
9
|
repository = "https://github.com/eitsupi/dlin"
|
|
@@ -34,7 +34,7 @@ insta = "1"
|
|
|
34
34
|
serial_test = "3.4.0"
|
|
35
35
|
|
|
36
36
|
# internal
|
|
37
|
-
dlin-core = { version = "0.2.0-alpha.
|
|
37
|
+
dlin-core = { version = "0.2.0-alpha.2", path = "crates/dlin-core" }
|
|
38
38
|
|
|
39
39
|
[workspace.lints.rust]
|
|
40
40
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
|
|
@@ -55,8 +55,8 @@ Examples:
|
|
|
55
55
|
dlin summary -o json # Project overview as JSON
|
|
56
56
|
dlin check-manifest || dbt compile # Recompile if stale or files deleted
|
|
57
57
|
git diff --name-only main | dlin graph # Lineage of changed files
|
|
58
|
-
dlin column
|
|
59
|
-
dlin column
|
|
58
|
+
dlin column upstream orders # Upstream: where do columns come from? (requires dbt compile)
|
|
59
|
+
dlin column downstream stg_orders --column order_id # Downstream: what depends on this column? (requires dbt compile)",
|
|
60
60
|
version
|
|
61
61
|
)]
|
|
62
62
|
pub struct Cli {
|
|
@@ -150,8 +150,8 @@ File paths are resolved to model names using dbt project configuration.
|
|
|
150
150
|
Column-level analysis:
|
|
151
151
|
This command works at the model level (bidirectional, with -u/-d depth control).
|
|
152
152
|
For column-level lineage tracing, see:
|
|
153
|
-
dlin column
|
|
154
|
-
dlin column
|
|
153
|
+
dlin column upstream — traces where each output column's data came from
|
|
154
|
+
dlin column downstream — finds which outputs depend on a given column
|
|
155
155
|
Both require manifest.json (run `dbt compile` first).",
|
|
156
156
|
after_long_help = "\
|
|
157
157
|
Examples:
|
|
@@ -207,8 +207,8 @@ Examples:
|
|
|
207
207
|
dlin graph -o mermaid --collapse --show-columns # rich detail on fewer nodes
|
|
208
208
|
|
|
209
209
|
# === Column-level analysis (requires manifest) ===
|
|
210
|
-
dlin column
|
|
211
|
-
dlin column
|
|
210
|
+
dlin column upstream orders # upstream: where do columns come from?
|
|
211
|
+
dlin column downstream stg_orders --column order_id # downstream: what depends on this column?"
|
|
212
212
|
)]
|
|
213
213
|
pub struct GraphArgs {
|
|
214
214
|
/// Model names to focus on (shows full lineage if omitted)
|
|
@@ -738,16 +738,16 @@ Column-level lineage and impact analysis.
|
|
|
738
738
|
Unlike `dlin graph` (model-level, bidirectional, with -u/-d depth control),
|
|
739
739
|
column analysis is split by direction — each subcommand covers one direction:
|
|
740
740
|
|
|
741
|
-
|
|
742
|
-
|
|
741
|
+
upstream — traces where each output column's data came from
|
|
742
|
+
downstream — finds which models/columns are affected by a column change
|
|
743
743
|
|
|
744
744
|
There are no -u/-d depth flags; the full chain is always traversed in both cases.
|
|
745
745
|
|
|
746
746
|
Both subcommands require manifest.json with compiled SQL (run `dbt compile` first).",
|
|
747
747
|
after_long_help = "\
|
|
748
748
|
Examples:
|
|
749
|
-
dlin column
|
|
750
|
-
dlin column
|
|
749
|
+
dlin column upstream orders # upstream: where do columns come from?
|
|
750
|
+
dlin column downstream stg_orders --column order_id # downstream: what depends on this column?"
|
|
751
751
|
)]
|
|
752
752
|
pub struct ColumnArgs {
|
|
753
753
|
#[command(subcommand)]
|
|
@@ -766,7 +766,7 @@ their raw source columns across the full DAG. There are no -u/-d depth flags
|
|
|
766
766
|
— the entire upstream chain is always traversed automatically.
|
|
767
767
|
|
|
768
768
|
To find what downstream models or columns would be affected by changing a
|
|
769
|
-
specific column, use `dlin column
|
|
769
|
+
specific column, use `dlin column downstream` instead.
|
|
770
770
|
|
|
771
771
|
Requires manifest.json with compiled SQL (run `dbt compile` first).
|
|
772
772
|
|
|
@@ -774,46 +774,55 @@ Column resolution order:
|
|
|
774
774
|
1. YAML column definitions (schema.yml / models.yml)
|
|
775
775
|
2. SQL inference from compiled_code (fallback when YAML is absent)
|
|
776
776
|
|
|
777
|
-
Output
|
|
778
|
-
model
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
777
|
+
Output format (-o/--output):
|
|
778
|
+
json (default) JSON array per model with the following structure:
|
|
779
|
+
model model name
|
|
780
|
+
traced_columns number of columns successfully traced
|
|
781
|
+
total_columns total number of columns attempted
|
|
782
|
+
columns[]
|
|
783
|
+
column output column name
|
|
784
|
+
transformation how the column was derived:
|
|
785
|
+
direct passed through unchanged (including renames)
|
|
786
|
+
aggregation aggregate function (SUM, COUNT, etc.)
|
|
787
|
+
expression arithmetic or other expression
|
|
788
|
+
cast type cast (CAST(x AS INT))
|
|
789
|
+
conditional CASE WHEN expression
|
|
790
|
+
unknown could not classify
|
|
791
|
+
sources[]
|
|
792
|
+
table source model or raw table name
|
|
793
|
+
column source column name
|
|
794
|
+
model_path[] intermediate models traversed (omitted if empty)
|
|
795
|
+
errors[] parse or resolution errors (non-empty → exit code 1)
|
|
796
|
+
plain human-readable text, one model per block
|
|
797
|
+
mermaid Mermaid flowchart (LR) with subgraphs per model
|
|
795
798
|
|
|
796
799
|
Exit codes:
|
|
797
800
|
0 Success
|
|
798
801
|
1 Error (model not found, no manifest, analysis errors, etc.)",
|
|
799
802
|
after_long_help = "\
|
|
800
803
|
Examples:
|
|
801
|
-
# Column lineage for a single model
|
|
802
|
-
dlin column
|
|
804
|
+
# Column lineage for a single model (JSON output)
|
|
805
|
+
dlin column upstream orders
|
|
806
|
+
|
|
807
|
+
# Human-readable plain output
|
|
808
|
+
dlin column upstream orders -o plain
|
|
809
|
+
|
|
810
|
+
# Mermaid flowchart
|
|
811
|
+
dlin column upstream orders -o mermaid
|
|
803
812
|
|
|
804
813
|
# Specific columns only
|
|
805
|
-
dlin column
|
|
814
|
+
dlin column upstream orders --column order_id --column status
|
|
806
815
|
|
|
807
816
|
# Multiple models
|
|
808
|
-
dlin column
|
|
817
|
+
dlin column upstream orders stg_orders
|
|
809
818
|
|
|
810
819
|
# With explicit manifest path
|
|
811
|
-
dlin column
|
|
820
|
+
dlin column upstream orders --manifest-path target/manifest.json
|
|
812
821
|
|
|
813
822
|
# BigQuery project
|
|
814
|
-
dlin column
|
|
823
|
+
dlin column upstream orders --dialect bigquery"
|
|
815
824
|
)]
|
|
816
|
-
|
|
825
|
+
Upstream(ColumnGraphArgs),
|
|
817
826
|
|
|
818
827
|
/// Analyze downstream column-level impact of changing a column
|
|
819
828
|
#[command(
|
|
@@ -824,33 +833,42 @@ Direction: downstream only. Starting from a specific column, follows forward
|
|
|
824
833
|
edges to find all dependent models and columns. There are no -u/-d depth flags
|
|
825
834
|
— all downstream dependents are always included.
|
|
826
835
|
|
|
827
|
-
This is the reverse direction of `dlin column
|
|
828
|
-
sources). To trace where a column's data comes from, use `dlin column
|
|
836
|
+
This is the reverse direction of `dlin column upstream` (which traces upstream
|
|
837
|
+
sources). To trace where a column's data comes from, use `dlin column upstream`.
|
|
829
838
|
|
|
830
839
|
Takes a single model and one or more --column flags (required).
|
|
831
840
|
|
|
832
841
|
Requires compiled SQL in manifest.json — run `dbt compile` first.
|
|
833
842
|
|
|
834
|
-
Output
|
|
843
|
+
Output format (-o/--output):
|
|
844
|
+
json (default) JSON array per column with affected downstream columns and models
|
|
845
|
+
plain human-readable text, one source column per block
|
|
846
|
+
mermaid Mermaid flowchart (LR) showing impacted columns across models
|
|
835
847
|
|
|
836
848
|
Exit codes:
|
|
837
849
|
0 Success
|
|
838
850
|
1 Error (model not found, no manifest, analysis errors, etc.)",
|
|
839
851
|
after_long_help = "\
|
|
840
852
|
Examples:
|
|
841
|
-
# Impact of changing a single column
|
|
842
|
-
dlin column
|
|
853
|
+
# Impact of changing a single column (JSON output)
|
|
854
|
+
dlin column downstream stg_orders --column order_id
|
|
855
|
+
|
|
856
|
+
# Human-readable plain output
|
|
857
|
+
dlin column downstream stg_orders --column order_id -o plain
|
|
858
|
+
|
|
859
|
+
# Mermaid flowchart
|
|
860
|
+
dlin column downstream stg_orders --column order_id -o mermaid
|
|
843
861
|
|
|
844
862
|
# Impact of multiple columns
|
|
845
|
-
dlin column
|
|
863
|
+
dlin column downstream stg_orders --column order_id --column status
|
|
846
864
|
|
|
847
865
|
# With explicit manifest path
|
|
848
|
-
dlin column
|
|
866
|
+
dlin column downstream stg_orders --column order_id --manifest-path target/manifest.json
|
|
849
867
|
|
|
850
868
|
# BigQuery project
|
|
851
|
-
dlin column
|
|
869
|
+
dlin column downstream stg_orders --column order_id --dialect bigquery"
|
|
852
870
|
)]
|
|
853
|
-
|
|
871
|
+
Downstream(ColumnImpactArgs),
|
|
854
872
|
}
|
|
855
873
|
|
|
856
874
|
#[derive(Debug, clap::Args)]
|
|
@@ -863,6 +881,10 @@ pub struct ColumnGraphArgs {
|
|
|
863
881
|
#[arg(long)]
|
|
864
882
|
pub column: Vec<String>,
|
|
865
883
|
|
|
884
|
+
/// Output format: json (default), plain, mermaid
|
|
885
|
+
#[arg(short = 'o', long, default_value = "json")]
|
|
886
|
+
pub output: ColumnOutputFormat,
|
|
887
|
+
|
|
866
888
|
/// SQL dialect for parsing (default: generic).
|
|
867
889
|
/// [possible values: bigquery, snowflake, postgres, redshift, databricks, spark, trino, duckdb, mysql, clickhouse, oracle, hive, sqlite, presto, athena, teradata, doris, starrocks, materialize, risingwave, singlestore, cockroachdb, tidb, tsql, druid, solr, tableau, dune, fabric, drill, dremio, exasol, datafusion]
|
|
868
890
|
#[arg(long)]
|
|
@@ -895,13 +917,17 @@ pub struct ColumnGraphArgs {
|
|
|
895
917
|
|
|
896
918
|
#[derive(Debug, clap::Args)]
|
|
897
919
|
pub struct ColumnImpactArgs {
|
|
898
|
-
/// Model name to analyze column impact for
|
|
920
|
+
/// Model name to analyze column downstream impact for
|
|
899
921
|
pub model: String,
|
|
900
922
|
|
|
901
923
|
/// Columns to analyze impact for (required)
|
|
902
924
|
#[arg(long, required = true)]
|
|
903
925
|
pub column: Vec<String>,
|
|
904
926
|
|
|
927
|
+
/// Output format: json (default), plain, mermaid
|
|
928
|
+
#[arg(short = 'o', long, default_value = "json")]
|
|
929
|
+
pub output: ColumnOutputFormat,
|
|
930
|
+
|
|
905
931
|
/// SQL dialect for parsing (default: generic).
|
|
906
932
|
/// [possible values: bigquery, snowflake, postgres, redshift, databricks, spark, trino, duckdb, mysql, clickhouse, oracle, hive, sqlite, presto, athena, teradata, doris, starrocks, materialize, risingwave, singlestore, cockroachdb, tidb, tsql, druid, solr, tableau, dune, fabric, drill, dremio, exasol, datafusion]
|
|
907
933
|
#[arg(long)]
|
|
@@ -1199,6 +1225,16 @@ pub enum ImpactOutputFormat {
|
|
|
1199
1225
|
Json,
|
|
1200
1226
|
}
|
|
1201
1227
|
|
|
1228
|
+
#[derive(Debug, Clone, PartialEq, Eq, clap::ValueEnum)]
|
|
1229
|
+
pub enum ColumnOutputFormat {
|
|
1230
|
+
/// Machine-readable JSON array (default)
|
|
1231
|
+
Json,
|
|
1232
|
+
/// Human-readable plain-text table
|
|
1233
|
+
Plain,
|
|
1234
|
+
/// Mermaid flowchart diagram
|
|
1235
|
+
Mermaid,
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1202
1238
|
#[cfg(test)]
|
|
1203
1239
|
mod tests {
|
|
1204
1240
|
use super::*;
|
|
@@ -1695,40 +1731,41 @@ mod tests {
|
|
|
1695
1731
|
assert_eq!(cli.error_format, ErrorFormat::Json);
|
|
1696
1732
|
}
|
|
1697
1733
|
|
|
1698
|
-
fn
|
|
1734
|
+
fn unwrap_column_upstream(cli: Cli) -> ColumnGraphArgs {
|
|
1699
1735
|
match cli.command {
|
|
1700
1736
|
Command::Column(col) => match col.command {
|
|
1701
|
-
ColumnCommand::
|
|
1702
|
-
_ => panic!("Expected Column
|
|
1737
|
+
ColumnCommand::Upstream(args) => args,
|
|
1738
|
+
_ => panic!("Expected Column upstream subcommand"),
|
|
1703
1739
|
},
|
|
1704
1740
|
_ => panic!("Expected Column subcommand"),
|
|
1705
1741
|
}
|
|
1706
1742
|
}
|
|
1707
1743
|
|
|
1708
|
-
fn
|
|
1744
|
+
fn unwrap_column_downstream(cli: Cli) -> ColumnImpactArgs {
|
|
1709
1745
|
match cli.command {
|
|
1710
1746
|
Command::Column(col) => match col.command {
|
|
1711
|
-
ColumnCommand::
|
|
1712
|
-
_ => panic!("Expected Column
|
|
1747
|
+
ColumnCommand::Downstream(args) => args,
|
|
1748
|
+
_ => panic!("Expected Column downstream subcommand"),
|
|
1713
1749
|
},
|
|
1714
1750
|
_ => panic!("Expected Column subcommand"),
|
|
1715
1751
|
}
|
|
1716
1752
|
}
|
|
1717
1753
|
|
|
1718
1754
|
#[test]
|
|
1719
|
-
fn
|
|
1720
|
-
let args =
|
|
1721
|
-
Cli::try_parse_from(["dlin", "column", "
|
|
1755
|
+
fn test_column_upstream_subcommand() {
|
|
1756
|
+
let args = unwrap_column_upstream(
|
|
1757
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "orders"]).unwrap(),
|
|
1722
1758
|
);
|
|
1723
1759
|
assert_eq!(args.model, &["orders"]);
|
|
1724
1760
|
assert!(args.column.is_empty());
|
|
1725
1761
|
}
|
|
1726
1762
|
|
|
1727
1763
|
#[test]
|
|
1728
|
-
fn
|
|
1729
|
-
let args =
|
|
1764
|
+
fn test_column_upstream_with_column_filter() {
|
|
1765
|
+
let args = unwrap_column_upstream(
|
|
1730
1766
|
Cli::try_parse_from([
|
|
1731
|
-
"dlin", "column", "
|
|
1767
|
+
"dlin", "column", "upstream", "orders", "--column", "order_id", "--column",
|
|
1768
|
+
"status",
|
|
1732
1769
|
])
|
|
1733
1770
|
.unwrap(),
|
|
1734
1771
|
);
|
|
@@ -1737,22 +1774,22 @@ mod tests {
|
|
|
1737
1774
|
}
|
|
1738
1775
|
|
|
1739
1776
|
#[test]
|
|
1740
|
-
fn
|
|
1777
|
+
fn test_column_upstream_no_model() {
|
|
1741
1778
|
// model is required at the clap level
|
|
1742
|
-
let result = Cli::try_parse_from(["dlin", "column", "
|
|
1779
|
+
let result = Cli::try_parse_from(["dlin", "column", "upstream"]);
|
|
1743
1780
|
assert!(
|
|
1744
1781
|
result.is_err(),
|
|
1745
|
-
"column
|
|
1782
|
+
"column upstream should require at least one model"
|
|
1746
1783
|
);
|
|
1747
1784
|
}
|
|
1748
1785
|
|
|
1749
1786
|
#[test]
|
|
1750
|
-
fn
|
|
1751
|
-
let args =
|
|
1787
|
+
fn test_column_downstream_subcommand() {
|
|
1788
|
+
let args = unwrap_column_downstream(
|
|
1752
1789
|
Cli::try_parse_from([
|
|
1753
1790
|
"dlin",
|
|
1754
1791
|
"column",
|
|
1755
|
-
"
|
|
1792
|
+
"downstream",
|
|
1756
1793
|
"stg_orders",
|
|
1757
1794
|
"--column",
|
|
1758
1795
|
"order_id",
|
|
@@ -1764,19 +1801,19 @@ mod tests {
|
|
|
1764
1801
|
}
|
|
1765
1802
|
|
|
1766
1803
|
#[test]
|
|
1767
|
-
fn
|
|
1768
|
-
// --column is required for column
|
|
1769
|
-
let result = Cli::try_parse_from(["dlin", "column", "
|
|
1770
|
-
assert!(result.is_err(), "column
|
|
1804
|
+
fn test_column_downstream_requires_column() {
|
|
1805
|
+
// --column is required for column downstream
|
|
1806
|
+
let result = Cli::try_parse_from(["dlin", "column", "downstream", "stg_orders"]);
|
|
1807
|
+
assert!(result.is_err(), "column downstream should require --column");
|
|
1771
1808
|
}
|
|
1772
1809
|
|
|
1773
1810
|
#[test]
|
|
1774
|
-
fn
|
|
1775
|
-
let args =
|
|
1811
|
+
fn test_column_downstream_multiple_columns() {
|
|
1812
|
+
let args = unwrap_column_downstream(
|
|
1776
1813
|
Cli::try_parse_from([
|
|
1777
1814
|
"dlin",
|
|
1778
1815
|
"column",
|
|
1779
|
-
"
|
|
1816
|
+
"downstream",
|
|
1780
1817
|
"stg_orders",
|
|
1781
1818
|
"--column",
|
|
1782
1819
|
"order_id",
|
|
@@ -1789,29 +1826,36 @@ mod tests {
|
|
|
1789
1826
|
}
|
|
1790
1827
|
|
|
1791
1828
|
#[test]
|
|
1792
|
-
fn
|
|
1793
|
-
let args =
|
|
1794
|
-
Cli::try_parse_from([
|
|
1795
|
-
|
|
1829
|
+
fn test_column_upstream_with_dialect() {
|
|
1830
|
+
let args = unwrap_column_upstream(
|
|
1831
|
+
Cli::try_parse_from([
|
|
1832
|
+
"dlin",
|
|
1833
|
+
"column",
|
|
1834
|
+
"upstream",
|
|
1835
|
+
"orders",
|
|
1836
|
+
"--dialect",
|
|
1837
|
+
"bigquery",
|
|
1838
|
+
])
|
|
1839
|
+
.unwrap(),
|
|
1796
1840
|
);
|
|
1797
1841
|
assert_eq!(args.dialect, Some(polyglot_sql::DialectType::BigQuery));
|
|
1798
1842
|
}
|
|
1799
1843
|
|
|
1800
1844
|
#[test]
|
|
1801
|
-
fn
|
|
1802
|
-
let args =
|
|
1803
|
-
Cli::try_parse_from(["dlin", "column", "
|
|
1845
|
+
fn test_column_upstream_default_dialect() {
|
|
1846
|
+
let args = unwrap_column_upstream(
|
|
1847
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "orders"]).unwrap(),
|
|
1804
1848
|
);
|
|
1805
1849
|
assert!(args.dialect.is_none());
|
|
1806
1850
|
}
|
|
1807
1851
|
|
|
1808
1852
|
#[test]
|
|
1809
|
-
fn
|
|
1810
|
-
let args =
|
|
1853
|
+
fn test_column_downstream_with_dialect() {
|
|
1854
|
+
let args = unwrap_column_downstream(
|
|
1811
1855
|
Cli::try_parse_from([
|
|
1812
1856
|
"dlin",
|
|
1813
1857
|
"column",
|
|
1814
|
-
"
|
|
1858
|
+
"downstream",
|
|
1815
1859
|
"stg_orders",
|
|
1816
1860
|
"--column",
|
|
1817
1861
|
"order_id",
|
|
@@ -1862,7 +1906,7 @@ mod tests {
|
|
|
1862
1906
|
];
|
|
1863
1907
|
for dialect in dialects {
|
|
1864
1908
|
let cli =
|
|
1865
|
-
Cli::try_parse_from(["dlin", "column", "
|
|
1909
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "model", "--dialect", dialect]);
|
|
1866
1910
|
assert!(
|
|
1867
1911
|
cli.is_ok(),
|
|
1868
1912
|
"dialect '{}' should parse successfully, got: {:?}",
|
|
@@ -1877,7 +1921,7 @@ mod tests {
|
|
|
1877
1921
|
let result = Cli::try_parse_from([
|
|
1878
1922
|
"dlin",
|
|
1879
1923
|
"column",
|
|
1880
|
-
"
|
|
1924
|
+
"upstream",
|
|
1881
1925
|
"model",
|
|
1882
1926
|
"--dialect",
|
|
1883
1927
|
"unknown_db",
|
|
@@ -1888,6 +1932,90 @@ mod tests {
|
|
|
1888
1932
|
);
|
|
1889
1933
|
}
|
|
1890
1934
|
|
|
1935
|
+
// -- ColumnOutputFormat tests --------------------------------------------
|
|
1936
|
+
|
|
1937
|
+
#[test]
|
|
1938
|
+
fn test_column_upstream_default_output_is_json() {
|
|
1939
|
+
let args = unwrap_column_upstream(
|
|
1940
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "orders"]).unwrap(),
|
|
1941
|
+
);
|
|
1942
|
+
assert!(matches!(args.output, ColumnOutputFormat::Json));
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
#[test]
|
|
1946
|
+
fn test_column_upstream_output_plain() {
|
|
1947
|
+
let args = unwrap_column_upstream(
|
|
1948
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "orders", "-o", "plain"]).unwrap(),
|
|
1949
|
+
);
|
|
1950
|
+
assert!(matches!(args.output, ColumnOutputFormat::Plain));
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
#[test]
|
|
1954
|
+
fn test_column_upstream_output_mermaid() {
|
|
1955
|
+
let args = unwrap_column_upstream(
|
|
1956
|
+
Cli::try_parse_from(["dlin", "column", "upstream", "orders", "-o", "mermaid"]).unwrap(),
|
|
1957
|
+
);
|
|
1958
|
+
assert!(matches!(args.output, ColumnOutputFormat::Mermaid));
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
#[test]
|
|
1962
|
+
fn test_column_upstream_invalid_output_rejected() {
|
|
1963
|
+
let result = Cli::try_parse_from(["dlin", "column", "upstream", "orders", "-o", "ascii"]);
|
|
1964
|
+
assert!(result.is_err(), "ascii is not a valid column output format");
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
#[test]
|
|
1968
|
+
fn test_column_downstream_default_output_is_json() {
|
|
1969
|
+
let args = unwrap_column_downstream(
|
|
1970
|
+
Cli::try_parse_from([
|
|
1971
|
+
"dlin",
|
|
1972
|
+
"column",
|
|
1973
|
+
"downstream",
|
|
1974
|
+
"stg_orders",
|
|
1975
|
+
"--column",
|
|
1976
|
+
"order_id",
|
|
1977
|
+
])
|
|
1978
|
+
.unwrap(),
|
|
1979
|
+
);
|
|
1980
|
+
assert!(matches!(args.output, ColumnOutputFormat::Json));
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
#[test]
|
|
1984
|
+
fn test_column_downstream_output_plain() {
|
|
1985
|
+
let args = unwrap_column_downstream(
|
|
1986
|
+
Cli::try_parse_from([
|
|
1987
|
+
"dlin",
|
|
1988
|
+
"column",
|
|
1989
|
+
"downstream",
|
|
1990
|
+
"stg_orders",
|
|
1991
|
+
"--column",
|
|
1992
|
+
"order_id",
|
|
1993
|
+
"-o",
|
|
1994
|
+
"plain",
|
|
1995
|
+
])
|
|
1996
|
+
.unwrap(),
|
|
1997
|
+
);
|
|
1998
|
+
assert!(matches!(args.output, ColumnOutputFormat::Plain));
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
#[test]
|
|
2002
|
+
fn test_column_downstream_output_mermaid() {
|
|
2003
|
+
let args = unwrap_column_downstream(
|
|
2004
|
+
Cli::try_parse_from([
|
|
2005
|
+
"dlin",
|
|
2006
|
+
"column",
|
|
2007
|
+
"downstream",
|
|
2008
|
+
"stg_orders",
|
|
2009
|
+
"--column",
|
|
2010
|
+
"order_id",
|
|
2011
|
+
"--output",
|
|
2012
|
+
"mermaid",
|
|
2013
|
+
])
|
|
2014
|
+
.unwrap(),
|
|
2015
|
+
);
|
|
2016
|
+
assert!(matches!(args.output, ColumnOutputFormat::Mermaid));
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1891
2019
|
// -- Debug subcommand tests -----------------------------------------------
|
|
1892
2020
|
|
|
1893
2021
|
fn unwrap_debug(cli: Cli) -> DebugArgs {
|