dlin-cli 0.2.0b1__tar.gz → 0.2.0b2__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.0b1 → dlin_cli-0.2.0b2}/Cargo.lock +4 -4
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/Cargo.toml +3 -3
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/PKG-INFO +1 -1
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin/Cargo.toml +1 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin/src/cli.rs +45 -2
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin/src/main.rs +14 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/core.rs +13 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs +23 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/filter.rs +160 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/manifest.rs +79 -4
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/column_graph.rs +137 -8
- dlin_cli-0.2.0b2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_non_direct_intermediate.snap +6 -0
- dlin_cli-0.2.0b2/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_model_path_non_direct_annotation.snap +6 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/LICENSE +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/README.md +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin/README.md +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin/tests/integration_test.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/Cargo.toml +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/README.md +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/error.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/builder.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/cache.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/cross_model.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/impact.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/mod.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/schema.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/single_model.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/cache.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/impact.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/types.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/impact.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/mod.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_bfs_pseudoendpoint.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_endpoints_fan_out.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_endpoints_leaf_model.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_multiple_focus_models.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_no_source_exposure.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__collapse_snapshot_preserve_focus.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_node_type_filter.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_select_filter.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/snapshots/dlin_core__graph__filter__tests__snapshot_transitive_select_with_node_type.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/types.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/input.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/lib.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/cache.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/columns.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/discovery.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/jinja.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/mod.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/project.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/sql.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/parser/yaml_schema.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/ascii.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/dot.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/html.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/impact.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/json.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/layout.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/list.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/mermaid.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/mod.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/plain.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_all_transformation_types.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_escapes_special_chars.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_id_collision_avoided.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_indirect.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_impact_single.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_single_model.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__dot_via_path.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_mermaid_indirect_edge_label.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__impact_plain_multi_hop.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_dotted_table_name.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_id_collision_avoided.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_label_escaping.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__mermaid_single_model.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_no_sources.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__column_graph__tests__plain_single_model.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_all_edge_types.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__dot__tests__snapshot_transitive_edges.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__html__tests__snapshot_html_json.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_json_with_sql.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__impact__tests__snapshot_impact_text_with_sql.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_json_with_sql.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__json__tests__snapshot_node_metadata.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_json.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__list__tests__snapshot_list_plain.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__group_by_node_type.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__mixed_direct_and_transitive_edges.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_escapes_quotes.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_lineage.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_single_model.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_collapse.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__show_columns_with_grouping.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_direction_tb_grouped.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_group_by_directory.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__snapshot_lineage.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__mermaid__tests__transitive_edge_rendering.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__plain__tests__snapshot_plain.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_json.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/snapshots/dlin_core__render__summary__tests__snapshot_summary_text.snap +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/summary.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/render/svg.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/tests/column_lineage_test.rs +0 -0
- {dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/pyproject.toml +0 -0
|
@@ -231,7 +231,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
|
231
231
|
|
|
232
232
|
[[package]]
|
|
233
233
|
name = "dlin"
|
|
234
|
-
version = "0.2.0-beta.
|
|
234
|
+
version = "0.2.0-beta.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-beta.
|
|
250
|
+
version = "0.2.0-beta.2"
|
|
251
251
|
dependencies = [
|
|
252
252
|
"anyhow",
|
|
253
253
|
"clap",
|
|
@@ -617,9 +617,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
|
|
617
617
|
|
|
618
618
|
[[package]]
|
|
619
619
|
name = "polyglot-sql"
|
|
620
|
-
version = "0.4.
|
|
620
|
+
version = "0.4.2"
|
|
621
621
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
622
|
-
checksum = "
|
|
622
|
+
checksum = "3e264f8907f3a2050232cd06503afb637525038ddd388a2c9e03424e336cd9c8"
|
|
623
623
|
dependencies = [
|
|
624
624
|
"serde",
|
|
625
625
|
"serde_json",
|
|
@@ -3,7 +3,7 @@ members = ["crates/*"]
|
|
|
3
3
|
resolver = "3"
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.2.0-beta.
|
|
6
|
+
version = "0.2.0-beta.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.4.
|
|
26
|
+
polyglot-sql = { version = "0.4.2", 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.0-beta.
|
|
37
|
+
dlin-core = { version = "0.2.0-beta.2", path = "crates/dlin-core" }
|
|
38
38
|
|
|
39
39
|
[workspace.lints.rust]
|
|
40
40
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
|
|
@@ -18,6 +18,7 @@ path = "src/main.rs"
|
|
|
18
18
|
dlin-core = { workspace = true, features = ["clap", "column-lineage"] }
|
|
19
19
|
clap = { workspace = true }
|
|
20
20
|
anyhow = { workspace = true }
|
|
21
|
+
regex = { workspace = true }
|
|
21
22
|
serde_json = { workspace = true }
|
|
22
23
|
path-slash = { workspace = true }
|
|
23
24
|
polyglot-sql = { workspace = true }
|
|
@@ -49,6 +49,8 @@ Examples:
|
|
|
49
49
|
dlin graph orders -u 2 -d 1 # orders with 2 upstream, 1 downstream
|
|
50
50
|
dlin graph -o json --json-full # JSON with all fields
|
|
51
51
|
dlin list -o json # List all node names as JSON
|
|
52
|
+
dlin list orders -o json --json-full # Model details: path, description, columns, materialization
|
|
53
|
+
dlin list --search shipping # Search models by name or description (regex)
|
|
52
54
|
dlin list orders stg_orders -o json # List specific models as JSON
|
|
53
55
|
dlin impact orders -o json # Downstream impact analysis
|
|
54
56
|
dlin summary # Project overview (node counts, etc.)
|
|
@@ -802,7 +804,9 @@ Output format (-o/--output):
|
|
|
802
804
|
conditional CASE WHEN expression
|
|
803
805
|
unknown could not classify
|
|
804
806
|
sources[]
|
|
805
|
-
table source model or raw table name
|
|
807
|
+
table source model or raw table name; empty string (\"\") when the
|
|
808
|
+
value originates from a literal (NULL, constant, UNNEST, etc.)
|
|
809
|
+
— rendered as \"(literal)\" in plain/mermaid/dot outputs
|
|
806
810
|
column source column name
|
|
807
811
|
model_path[] intermediate [model, column, transformation] triples traversed (omitted if empty)
|
|
808
812
|
errors[] parse or resolution errors (non-empty → exit code 1)
|
|
@@ -1081,6 +1085,13 @@ Examples:
|
|
|
1081
1085
|
# List models tagged 'finance'
|
|
1082
1086
|
dlin list -s tag:finance
|
|
1083
1087
|
|
|
1088
|
+
# Search models by name or description (regex, case-insensitive)
|
|
1089
|
+
dlin list --search shipping
|
|
1090
|
+
dlin list --search '^stg_' # models whose name starts with stg_
|
|
1091
|
+
dlin list --search 'order|payment' # OR: name/description contains either
|
|
1092
|
+
dlin list --search staging --search customer # AND: must match both patterns
|
|
1093
|
+
dlin list --search shipping -o json --json-full
|
|
1094
|
+
|
|
1084
1095
|
# Count models (combine with standard tools)
|
|
1085
1096
|
dlin list --node-type model | wc -l
|
|
1086
1097
|
|
|
@@ -1088,7 +1099,13 @@ Examples:
|
|
|
1088
1099
|
dlin impact orders -o json | jq -r '.[].impacted_nodes[].unique_id' | dlin list -o json --json-fields unique_id,sql_content
|
|
1089
1100
|
|
|
1090
1101
|
# List models from changed files
|
|
1091
|
-
git diff --name-only main | dlin list -o json --json-fields unique_id,label
|
|
1102
|
+
git diff --name-only main | dlin list -o json --json-fields unique_id,label
|
|
1103
|
+
|
|
1104
|
+
# Find models that expose a specific column name (jq)
|
|
1105
|
+
dlin list -o json --json-full | jq '.[] | select(any(.columns[]; . == \"order_id\"))'
|
|
1106
|
+
|
|
1107
|
+
# Find models whose column name partially matches (jq)
|
|
1108
|
+
dlin list -o json --json-full | jq '.[] | select(any(.columns[]; contains(\"_amount\")))' "
|
|
1092
1109
|
)]
|
|
1093
1110
|
pub struct ListArgs {
|
|
1094
1111
|
/// Model names to list (lists all nodes if omitted)
|
|
@@ -1128,6 +1145,32 @@ All selectors support glob patterns (*, **, ?, []):
|
|
|
1128
1145
|
)]
|
|
1129
1146
|
pub select: Option<String>,
|
|
1130
1147
|
|
|
1148
|
+
/// Filter nodes by name or description using a regex pattern (case-insensitive; repeatable for AND)
|
|
1149
|
+
#[arg(
|
|
1150
|
+
long,
|
|
1151
|
+
value_name = "PATTERN",
|
|
1152
|
+
action = clap::ArgAction::Append,
|
|
1153
|
+
long_help = "\
|
|
1154
|
+
Filter nodes whose name or description matches the regex pattern (case-insensitive).
|
|
1155
|
+
|
|
1156
|
+
Matching rules:
|
|
1157
|
+
- Tested against model name and description field (OR within a single pattern)
|
|
1158
|
+
- Plain text works as a simple substring match
|
|
1159
|
+
- Repeating --search applies AND logic: all patterns must match
|
|
1160
|
+
|
|
1161
|
+
Regex syntax (Rust regex, https://docs.rs/regex):
|
|
1162
|
+
order|payment match nodes containing 'order' or 'payment'
|
|
1163
|
+
^stg_ match nodes whose name starts with 'stg_'
|
|
1164
|
+
(?-i)Order opt out of case-insensitivity for this pattern
|
|
1165
|
+
|
|
1166
|
+
Examples:
|
|
1167
|
+
dlin list --search shipping
|
|
1168
|
+
dlin list --search '^stg_'
|
|
1169
|
+
dlin list --search 'order|payment'
|
|
1170
|
+
dlin list --search staging --search customer # AND: must match both"
|
|
1171
|
+
)]
|
|
1172
|
+
pub search: Vec<String>,
|
|
1173
|
+
|
|
1131
1174
|
/// Filter output by node type (comma-separated)
|
|
1132
1175
|
#[arg(
|
|
1133
1176
|
long = "node-type",
|
|
@@ -5,6 +5,7 @@ use anyhow::Result;
|
|
|
5
5
|
use clap::Parser;
|
|
6
6
|
use path_slash::PathExt as _;
|
|
7
7
|
use polyglot_sql::{DialectType, Schema as _};
|
|
8
|
+
use regex::RegexBuilder;
|
|
8
9
|
|
|
9
10
|
mod cli;
|
|
10
11
|
|
|
@@ -360,6 +361,19 @@ fn run_list_command(args: ListArgs) -> Result<()> {
|
|
|
360
361
|
);
|
|
361
362
|
}
|
|
362
363
|
let filtered = graph::filter::filter_output_node_types(&filtered, &type_names, false);
|
|
364
|
+
|
|
365
|
+
// Compile search patterns and apply filter (AND across all patterns)
|
|
366
|
+
let search_patterns = args
|
|
367
|
+
.search
|
|
368
|
+
.iter()
|
|
369
|
+
.map(|p| {
|
|
370
|
+
RegexBuilder::new(p)
|
|
371
|
+
.case_insensitive(true)
|
|
372
|
+
.build()
|
|
373
|
+
.map_err(|e| anyhow::anyhow!("invalid --search pattern {:?}: {}", p, e))
|
|
374
|
+
})
|
|
375
|
+
.collect::<Result<Vec<_>>>()?;
|
|
376
|
+
let filtered = graph::filter::filter_by_search(&filtered, &search_patterns);
|
|
363
377
|
warn_sql_mode_test_limitation(
|
|
364
378
|
&args.source,
|
|
365
379
|
filtered
|
{dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/core.rs
RENAMED
|
@@ -971,6 +971,7 @@ fn test_cte_alias_resolution() {
|
|
|
971
971
|
resource_type: "source".to_string(),
|
|
972
972
|
description: None,
|
|
973
973
|
path: None,
|
|
974
|
+
original_file_path: None,
|
|
974
975
|
columns: src_cols,
|
|
975
976
|
database: None,
|
|
976
977
|
schema: None,
|
|
@@ -1000,6 +1001,7 @@ fn test_cte_alias_resolution() {
|
|
|
1000
1001
|
config: ManifestConfig::default(),
|
|
1001
1002
|
description: None,
|
|
1002
1003
|
path: None,
|
|
1004
|
+
original_file_path: None,
|
|
1003
1005
|
columns: stg_cols,
|
|
1004
1006
|
compiled_code: Some("select id as item_id, name, status from items".to_string()),
|
|
1005
1007
|
database: None,
|
|
@@ -1029,6 +1031,7 @@ fn test_cte_alias_resolution() {
|
|
|
1029
1031
|
config: ManifestConfig::default(),
|
|
1030
1032
|
description: None,
|
|
1031
1033
|
path: None,
|
|
1034
|
+
original_file_path: None,
|
|
1032
1035
|
columns: mart_cols,
|
|
1033
1036
|
compiled_code: Some(
|
|
1034
1037
|
concat!(
|
|
@@ -1104,6 +1107,7 @@ fn test_select_star_chain_with_join() {
|
|
|
1104
1107
|
resource_type: "source".to_string(),
|
|
1105
1108
|
description: None,
|
|
1106
1109
|
path: None,
|
|
1110
|
+
original_file_path: None,
|
|
1107
1111
|
columns: user_cols,
|
|
1108
1112
|
database: None,
|
|
1109
1113
|
schema: None,
|
|
@@ -1130,6 +1134,7 @@ fn test_select_star_chain_with_join() {
|
|
|
1130
1134
|
resource_type: "source".to_string(),
|
|
1131
1135
|
description: None,
|
|
1132
1136
|
path: None,
|
|
1137
|
+
original_file_path: None,
|
|
1133
1138
|
columns: region_cols,
|
|
1134
1139
|
database: None,
|
|
1135
1140
|
schema: None,
|
|
@@ -1159,6 +1164,7 @@ fn test_select_star_chain_with_join() {
|
|
|
1159
1164
|
config: ManifestConfig::default(),
|
|
1160
1165
|
description: None,
|
|
1161
1166
|
path: None,
|
|
1167
|
+
original_file_path: None,
|
|
1162
1168
|
columns: stg_user_cols,
|
|
1163
1169
|
compiled_code: Some("select id, name, area from users".to_string()),
|
|
1164
1170
|
database: Some("mydb".to_string()),
|
|
@@ -1188,6 +1194,7 @@ fn test_select_star_chain_with_join() {
|
|
|
1188
1194
|
config: ManifestConfig::default(),
|
|
1189
1195
|
description: None,
|
|
1190
1196
|
path: None,
|
|
1197
|
+
original_file_path: None,
|
|
1191
1198
|
columns: stg_region_cols,
|
|
1192
1199
|
compiled_code: Some("select id, region_name from regions".to_string()),
|
|
1193
1200
|
database: Some("mydb".to_string()),
|
|
@@ -1221,6 +1228,7 @@ fn test_select_star_chain_with_join() {
|
|
|
1221
1228
|
config: ManifestConfig::default(),
|
|
1222
1229
|
description: None,
|
|
1223
1230
|
path: None,
|
|
1231
|
+
original_file_path: None,
|
|
1224
1232
|
columns: mart_cols,
|
|
1225
1233
|
compiled_code: Some(
|
|
1226
1234
|
concat!(
|
|
@@ -1322,6 +1330,7 @@ fn test_select_star_chain_with_cte_alias_and_join() {
|
|
|
1322
1330
|
resource_type: "source".to_string(),
|
|
1323
1331
|
description: None,
|
|
1324
1332
|
path: None,
|
|
1333
|
+
original_file_path: None,
|
|
1325
1334
|
columns: user_cols,
|
|
1326
1335
|
database: None,
|
|
1327
1336
|
schema: None,
|
|
@@ -1348,6 +1357,7 @@ fn test_select_star_chain_with_cte_alias_and_join() {
|
|
|
1348
1357
|
resource_type: "source".to_string(),
|
|
1349
1358
|
description: None,
|
|
1350
1359
|
path: None,
|
|
1360
|
+
original_file_path: None,
|
|
1351
1361
|
columns: region_cols,
|
|
1352
1362
|
database: None,
|
|
1353
1363
|
schema: None,
|
|
@@ -1377,6 +1387,7 @@ fn test_select_star_chain_with_cte_alias_and_join() {
|
|
|
1377
1387
|
config: ManifestConfig::default(),
|
|
1378
1388
|
description: None,
|
|
1379
1389
|
path: None,
|
|
1390
|
+
original_file_path: None,
|
|
1380
1391
|
columns: stg_user_cols,
|
|
1381
1392
|
compiled_code: Some("select id, name, area from users".to_string()),
|
|
1382
1393
|
database: Some("mydb".to_string()),
|
|
@@ -1406,6 +1417,7 @@ fn test_select_star_chain_with_cte_alias_and_join() {
|
|
|
1406
1417
|
config: ManifestConfig::default(),
|
|
1407
1418
|
description: None,
|
|
1408
1419
|
path: None,
|
|
1420
|
+
original_file_path: None,
|
|
1409
1421
|
columns: stg_region_cols,
|
|
1410
1422
|
compiled_code: Some("select id, region_name from regions".to_string()),
|
|
1411
1423
|
database: Some("mydb".to_string()),
|
|
@@ -1439,6 +1451,7 @@ fn test_select_star_chain_with_cte_alias_and_join() {
|
|
|
1439
1451
|
config: ManifestConfig::default(),
|
|
1440
1452
|
description: None,
|
|
1441
1453
|
path: None,
|
|
1454
|
+
original_file_path: None,
|
|
1442
1455
|
columns: mart_cols,
|
|
1443
1456
|
compiled_code: Some(
|
|
1444
1457
|
concat!(
|
{dlin_cli-0.2.0b1 → dlin_cli-0.2.0b2}/crates/dlin-core/src/graph/column_lineage/tests/mod.rs
RENAMED
|
@@ -36,6 +36,7 @@ fn make_test_manifest() -> Manifest {
|
|
|
36
36
|
config: ManifestConfig::default(),
|
|
37
37
|
description: None,
|
|
38
38
|
path: None,
|
|
39
|
+
original_file_path: None,
|
|
39
40
|
columns: stg_orders_cols,
|
|
40
41
|
compiled_code: Some(
|
|
41
42
|
"select id as order_id, user_id as customer_id, order_date, status from raw.orders"
|
|
@@ -67,6 +68,7 @@ fn make_test_manifest() -> Manifest {
|
|
|
67
68
|
config: ManifestConfig::default(),
|
|
68
69
|
description: None,
|
|
69
70
|
path: None,
|
|
71
|
+
original_file_path: None,
|
|
70
72
|
columns: orders_cols,
|
|
71
73
|
compiled_code: Some("select o.order_id, o.customer_id, p.amount as total_amount from stg_orders o left join stg_payments p on o.order_id = p.order_id".to_string()),
|
|
72
74
|
database: None,
|
|
@@ -93,6 +95,7 @@ fn make_test_manifest() -> Manifest {
|
|
|
93
95
|
config: ManifestConfig::default(),
|
|
94
96
|
description: None,
|
|
95
97
|
path: None,
|
|
98
|
+
original_file_path: None,
|
|
96
99
|
columns: stg_payments_cols,
|
|
97
100
|
compiled_code: Some(
|
|
98
101
|
"select id as payment_id, order_id, amount, payment_method from raw.payments"
|
|
@@ -123,6 +126,7 @@ fn make_test_manifest() -> Manifest {
|
|
|
123
126
|
resource_type: "source".to_string(),
|
|
124
127
|
description: None,
|
|
125
128
|
path: None,
|
|
129
|
+
original_file_path: None,
|
|
126
130
|
columns: source_cols,
|
|
127
131
|
database: None,
|
|
128
132
|
schema: None,
|
|
@@ -160,6 +164,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
160
164
|
resource_type: "source".to_string(),
|
|
161
165
|
description: None,
|
|
162
166
|
path: None,
|
|
167
|
+
original_file_path: None,
|
|
163
168
|
columns: raw_orders_cols,
|
|
164
169
|
database: None,
|
|
165
170
|
schema: None,
|
|
@@ -186,6 +191,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
186
191
|
resource_type: "source".to_string(),
|
|
187
192
|
description: None,
|
|
188
193
|
path: None,
|
|
194
|
+
original_file_path: None,
|
|
189
195
|
columns: raw_payments_cols,
|
|
190
196
|
database: None,
|
|
191
197
|
schema: None,
|
|
@@ -215,6 +221,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
215
221
|
config: ManifestConfig::default(),
|
|
216
222
|
description: None,
|
|
217
223
|
path: None,
|
|
224
|
+
original_file_path: None,
|
|
218
225
|
columns: stg_orders_cols,
|
|
219
226
|
compiled_code: Some(
|
|
220
227
|
"select id as order_id, user_id as customer_id, order_date, status from orders"
|
|
@@ -247,6 +254,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
247
254
|
config: ManifestConfig::default(),
|
|
248
255
|
description: None,
|
|
249
256
|
path: None,
|
|
257
|
+
original_file_path: None,
|
|
250
258
|
columns: stg_payments_cols,
|
|
251
259
|
compiled_code: Some(
|
|
252
260
|
"select id as payment_id, order_id, amount, payment_method from payments"
|
|
@@ -282,6 +290,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
282
290
|
config: ManifestConfig::default(),
|
|
283
291
|
description: None,
|
|
284
292
|
path: None,
|
|
293
|
+
original_file_path: None,
|
|
285
294
|
columns: orders_cols,
|
|
286
295
|
compiled_code: Some(
|
|
287
296
|
concat!(
|
|
@@ -321,6 +330,7 @@ fn make_cross_model_manifest() -> Manifest {
|
|
|
321
330
|
config: ManifestConfig::default(),
|
|
322
331
|
description: None,
|
|
323
332
|
path: None,
|
|
333
|
+
original_file_path: None,
|
|
324
334
|
columns: customers_cols,
|
|
325
335
|
compiled_code: Some(
|
|
326
336
|
concat!(
|
|
@@ -355,6 +365,7 @@ fn make_duplicate_name_manifest() -> Manifest {
|
|
|
355
365
|
config: ManifestConfig::default(),
|
|
356
366
|
description: None,
|
|
357
367
|
path: None,
|
|
368
|
+
original_file_path: None,
|
|
358
369
|
columns: {
|
|
359
370
|
let mut cols = HashMap::new();
|
|
360
371
|
cols.insert(
|
|
@@ -384,6 +395,7 @@ fn make_duplicate_name_manifest() -> Manifest {
|
|
|
384
395
|
config: ManifestConfig::default(),
|
|
385
396
|
description: None,
|
|
386
397
|
path: None,
|
|
398
|
+
original_file_path: None,
|
|
387
399
|
columns: {
|
|
388
400
|
let mut cols = HashMap::new();
|
|
389
401
|
cols.insert(
|
|
@@ -413,6 +425,7 @@ fn make_duplicate_name_manifest() -> Manifest {
|
|
|
413
425
|
config: ManifestConfig::default(),
|
|
414
426
|
description: None,
|
|
415
427
|
path: None,
|
|
428
|
+
original_file_path: None,
|
|
416
429
|
columns: {
|
|
417
430
|
let mut cols = HashMap::new();
|
|
418
431
|
cols.insert(
|
|
@@ -508,6 +521,7 @@ fn make_diamond_manifest() -> Manifest {
|
|
|
508
521
|
config: ManifestConfig::default(),
|
|
509
522
|
description: None,
|
|
510
523
|
path: None,
|
|
524
|
+
original_file_path: None,
|
|
511
525
|
columns: raw_cols,
|
|
512
526
|
compiled_code: Some("select x, y from source_table".to_string()),
|
|
513
527
|
database: None,
|
|
@@ -537,6 +551,7 @@ fn make_diamond_manifest() -> Manifest {
|
|
|
537
551
|
config: ManifestConfig::default(),
|
|
538
552
|
description: None,
|
|
539
553
|
path: None,
|
|
554
|
+
original_file_path: None,
|
|
540
555
|
columns: shared_cols,
|
|
541
556
|
compiled_code: Some("select x, y from raw_data".to_string()),
|
|
542
557
|
database: None,
|
|
@@ -564,6 +579,7 @@ fn make_diamond_manifest() -> Manifest {
|
|
|
564
579
|
config: ManifestConfig::default(),
|
|
565
580
|
description: None,
|
|
566
581
|
path: None,
|
|
582
|
+
original_file_path: None,
|
|
567
583
|
columns: left_cols,
|
|
568
584
|
compiled_code: Some("select x from shared".to_string()),
|
|
569
585
|
database: None,
|
|
@@ -591,6 +607,7 @@ fn make_diamond_manifest() -> Manifest {
|
|
|
591
607
|
config: ManifestConfig::default(),
|
|
592
608
|
description: None,
|
|
593
609
|
path: None,
|
|
610
|
+
original_file_path: None,
|
|
594
611
|
columns: right_cols,
|
|
595
612
|
compiled_code: Some("select y from shared".to_string()),
|
|
596
613
|
database: None,
|
|
@@ -623,6 +640,7 @@ fn make_diamond_manifest() -> Manifest {
|
|
|
623
640
|
config: ManifestConfig::default(),
|
|
624
641
|
description: None,
|
|
625
642
|
path: None,
|
|
643
|
+
original_file_path: None,
|
|
626
644
|
columns: out_cols,
|
|
627
645
|
compiled_code: Some(
|
|
628
646
|
"select l.x as lx, r.y as ry from left_model l join right_model r on 1=1"
|
|
@@ -663,6 +681,7 @@ pub(super) fn make_transformation_manifest() -> Manifest {
|
|
|
663
681
|
resource_type: "source".to_string(),
|
|
664
682
|
description: None,
|
|
665
683
|
path: None,
|
|
684
|
+
original_file_path: None,
|
|
666
685
|
columns: raw_cols,
|
|
667
686
|
database: None,
|
|
668
687
|
schema: None,
|
|
@@ -692,6 +711,7 @@ pub(super) fn make_transformation_manifest() -> Manifest {
|
|
|
692
711
|
config: ManifestConfig::default(),
|
|
693
712
|
description: None,
|
|
694
713
|
path: None,
|
|
714
|
+
original_file_path: None,
|
|
695
715
|
columns: scalar_cols,
|
|
696
716
|
compiled_code: Some(
|
|
697
717
|
concat!(
|
|
@@ -730,6 +750,7 @@ pub(super) fn make_transformation_manifest() -> Manifest {
|
|
|
730
750
|
config: ManifestConfig::default(),
|
|
731
751
|
description: None,
|
|
732
752
|
path: None,
|
|
753
|
+
original_file_path: None,
|
|
733
754
|
columns: pt_upper_cols,
|
|
734
755
|
compiled_code: Some(
|
|
735
756
|
concat!(
|
|
@@ -767,6 +788,7 @@ pub(super) fn make_transformation_manifest() -> Manifest {
|
|
|
767
788
|
config: ManifestConfig::default(),
|
|
768
789
|
description: None,
|
|
769
790
|
path: None,
|
|
791
|
+
original_file_path: None,
|
|
770
792
|
columns: pt_coalesce_cols,
|
|
771
793
|
compiled_code: Some(
|
|
772
794
|
concat!(
|
|
@@ -819,6 +841,7 @@ pub(super) fn make_reconverging_manifest() -> Manifest {
|
|
|
819
841
|
config: ManifestConfig::default(),
|
|
820
842
|
description: None,
|
|
821
843
|
path: None,
|
|
844
|
+
original_file_path: None,
|
|
822
845
|
columns: {
|
|
823
846
|
let mut cols = HashMap::new();
|
|
824
847
|
cols.insert(
|
|
@@ -512,6 +512,28 @@ pub fn collapse_intermediate(
|
|
|
512
512
|
build_subgraph_with_transitive(graph, &keep)
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
+
/// Filter graph to nodes matching all of the given regex patterns (AND logic).
|
|
516
|
+
///
|
|
517
|
+
/// Each pattern is tested against the node's label and description (OR within a single pattern).
|
|
518
|
+
/// A node is kept only if every pattern matches at least one of those fields.
|
|
519
|
+
/// An empty slice returns the graph unchanged.
|
|
520
|
+
pub fn filter_by_search(graph: &LineageGraph, patterns: &[regex::Regex]) -> LineageGraph {
|
|
521
|
+
if patterns.is_empty() {
|
|
522
|
+
return graph.clone();
|
|
523
|
+
}
|
|
524
|
+
let keep: HashSet<NodeIndex> = graph
|
|
525
|
+
.node_indices()
|
|
526
|
+
.filter(|&idx| {
|
|
527
|
+
let node = &graph[idx];
|
|
528
|
+
patterns.iter().all(|re| {
|
|
529
|
+
re.is_match(&node.label)
|
|
530
|
+
|| node.description.as_deref().is_some_and(|d| re.is_match(d))
|
|
531
|
+
})
|
|
532
|
+
})
|
|
533
|
+
.collect();
|
|
534
|
+
build_subgraph(graph, &keep)
|
|
535
|
+
}
|
|
536
|
+
|
|
515
537
|
/// BFS traversal collecting nodes up to max_depth levels away
|
|
516
538
|
fn bfs_collect(
|
|
517
539
|
graph: &LineageGraph,
|
|
@@ -2233,4 +2255,142 @@ mod tests {
|
|
|
2233
2255
|
let filtered = filter_output_node_types(&g, &["source".into(), "model".into()], true);
|
|
2234
2256
|
insta::assert_snapshot!(render_mermaid(&filtered));
|
|
2235
2257
|
}
|
|
2258
|
+
|
|
2259
|
+
// -- filter_by_search tests -----------------------------------------------
|
|
2260
|
+
|
|
2261
|
+
fn make_node_with_desc(unique_id: &str, label: &str, description: Option<&str>) -> NodeData {
|
|
2262
|
+
NodeData {
|
|
2263
|
+
unique_id: unique_id.into(),
|
|
2264
|
+
label: label.into(),
|
|
2265
|
+
node_type: NodeType::Model,
|
|
2266
|
+
file_path: None,
|
|
2267
|
+
description: description.map(|s| s.to_string()),
|
|
2268
|
+
materialization: None,
|
|
2269
|
+
tags: vec![],
|
|
2270
|
+
columns: vec![],
|
|
2271
|
+
exposure: None,
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
fn make_search_graph() -> LineageGraph {
|
|
2276
|
+
let mut g = LineageGraph::new();
|
|
2277
|
+
g.add_node(make_node_with_desc(
|
|
2278
|
+
"model.stg_orders",
|
|
2279
|
+
"stg_orders",
|
|
2280
|
+
Some("Staging model for order data"),
|
|
2281
|
+
));
|
|
2282
|
+
g.add_node(make_node_with_desc(
|
|
2283
|
+
"model.stg_customers",
|
|
2284
|
+
"stg_customers",
|
|
2285
|
+
Some("Staging model for customer data"),
|
|
2286
|
+
));
|
|
2287
|
+
g.add_node(make_node_with_desc(
|
|
2288
|
+
"model.order_summary",
|
|
2289
|
+
"order_summary",
|
|
2290
|
+
None,
|
|
2291
|
+
));
|
|
2292
|
+
g.add_node(make_node_with_desc("model.payments", "payments", None));
|
|
2293
|
+
g
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
fn re(pattern: &str) -> regex::Regex {
|
|
2297
|
+
regex::RegexBuilder::new(pattern)
|
|
2298
|
+
.case_insensitive(true)
|
|
2299
|
+
.build()
|
|
2300
|
+
.unwrap()
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
#[test]
|
|
2304
|
+
fn test_search_by_label() {
|
|
2305
|
+
let g = make_search_graph();
|
|
2306
|
+
let result = filter_by_search(&g, &[re("order")]);
|
|
2307
|
+
let labels: HashSet<String> = result
|
|
2308
|
+
.node_indices()
|
|
2309
|
+
.map(|i| result[i].label.clone())
|
|
2310
|
+
.collect();
|
|
2311
|
+
assert!(labels.contains("stg_orders"));
|
|
2312
|
+
assert!(labels.contains("order_summary"));
|
|
2313
|
+
assert!(!labels.contains("stg_customers"));
|
|
2314
|
+
assert!(!labels.contains("payments"));
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
#[test]
|
|
2318
|
+
fn test_search_by_description() {
|
|
2319
|
+
let g = make_search_graph();
|
|
2320
|
+
// "customer" only appears in stg_customers description
|
|
2321
|
+
let result = filter_by_search(&g, &[re("customer")]);
|
|
2322
|
+
let labels: HashSet<String> = result
|
|
2323
|
+
.node_indices()
|
|
2324
|
+
.map(|i| result[i].label.clone())
|
|
2325
|
+
.collect();
|
|
2326
|
+
assert!(labels.contains("stg_customers"));
|
|
2327
|
+
assert_eq!(result.node_count(), 1);
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
#[test]
|
|
2331
|
+
fn test_search_case_insensitive() {
|
|
2332
|
+
let g = make_search_graph();
|
|
2333
|
+
let result_lower = filter_by_search(&g, &[re("staging")]);
|
|
2334
|
+
let result_upper = filter_by_search(&g, &[re("STAGING")]);
|
|
2335
|
+
let result_mixed = filter_by_search(&g, &[re("Staging")]);
|
|
2336
|
+
assert_eq!(result_lower.node_count(), result_upper.node_count());
|
|
2337
|
+
assert_eq!(result_lower.node_count(), result_mixed.node_count());
|
|
2338
|
+
assert_eq!(result_lower.node_count(), 2); // stg_orders and stg_customers descriptions
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
#[test]
|
|
2342
|
+
fn test_search_no_match() {
|
|
2343
|
+
let g = make_search_graph();
|
|
2344
|
+
let result = filter_by_search(&g, &[re("nonexistent_xyz")]);
|
|
2345
|
+
assert_eq!(result.node_count(), 0);
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
#[test]
|
|
2349
|
+
fn test_search_empty_patterns_returns_all() {
|
|
2350
|
+
let g = make_search_graph();
|
|
2351
|
+
let result = filter_by_search(&g, &[]);
|
|
2352
|
+
assert_eq!(result.node_count(), g.node_count());
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
#[test]
|
|
2356
|
+
fn test_search_multiple_patterns_and_logic() {
|
|
2357
|
+
let g = make_search_graph();
|
|
2358
|
+
// Both "stg" AND "order" must match — only stg_orders qualifies
|
|
2359
|
+
let result = filter_by_search(&g, &[re("stg"), re("order")]);
|
|
2360
|
+
let labels: HashSet<String> = result
|
|
2361
|
+
.node_indices()
|
|
2362
|
+
.map(|i| result[i].label.clone())
|
|
2363
|
+
.collect();
|
|
2364
|
+
assert_eq!(result.node_count(), 1);
|
|
2365
|
+
assert!(labels.contains("stg_orders"));
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
#[test]
|
|
2369
|
+
fn test_search_regex_alternation() {
|
|
2370
|
+
let g = make_search_graph();
|
|
2371
|
+
// OR via regex alternation: matches stg_orders, stg_customers, payments
|
|
2372
|
+
let result = filter_by_search(&g, &[re("customer|payment")]);
|
|
2373
|
+
let labels: HashSet<String> = result
|
|
2374
|
+
.node_indices()
|
|
2375
|
+
.map(|i| result[i].label.clone())
|
|
2376
|
+
.collect();
|
|
2377
|
+
assert!(labels.contains("stg_customers"));
|
|
2378
|
+
assert!(labels.contains("payments"));
|
|
2379
|
+
assert!(!labels.contains("stg_orders"));
|
|
2380
|
+
assert!(!labels.contains("order_summary"));
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
#[test]
|
|
2384
|
+
fn test_search_regex_pattern() {
|
|
2385
|
+
let g = make_search_graph();
|
|
2386
|
+
// Regex: labels starting with "stg_"
|
|
2387
|
+
let result = filter_by_search(&g, &[re("^stg_")]);
|
|
2388
|
+
let labels: HashSet<String> = result
|
|
2389
|
+
.node_indices()
|
|
2390
|
+
.map(|i| result[i].label.clone())
|
|
2391
|
+
.collect();
|
|
2392
|
+
assert!(labels.contains("stg_orders"));
|
|
2393
|
+
assert!(labels.contains("stg_customers"));
|
|
2394
|
+
assert_eq!(result.node_count(), 2);
|
|
2395
|
+
}
|
|
2236
2396
|
}
|