sql-glider 0.1.21__tar.gz → 0.1.24__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.
- {sql_glider-0.1.21 → sql_glider-0.1.24}/CLAUDE.md +9 -0
- sql_glider-0.1.21/README.md → sql_glider-0.1.24/PKG-INFO +83 -1
- sql_glider-0.1.21/PKG-INFO → sql_glider-0.1.24/README.md +49 -33
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/docs/graph-lineage.md +55 -1
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/zensical.toml +6 -4
- sql_glider-0.1.24/examples/plotly_viewer.py +109 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/pyproject.toml +3 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/_version.py +2 -2
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/cli.py +46 -17
- sql_glider-0.1.24/src/sqlglider/graph/diagram_formatters.py +658 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_diagram_formatters.py +287 -1
- {sql_glider-0.1.21 → sql_glider-0.1.24}/uv.lock +146 -1
- sql_glider-0.1.21/src/sqlglider/graph/diagram_formatters.py +0 -330
- {sql_glider-0.1.21 → sql_glider-0.1.24}/.github/workflows/ci.yml +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/.github/workflows/docs.yml +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/.github/workflows/publish.yml +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/.gitignore +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/.python-version +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/ARCHITECTURE.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/LICENSE +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/.github/workflows/docs.yml +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/docs/catalogs.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/docs/index.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/docs/static/sqlglider-logo-transparent.png +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/docs/docs/templating.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-05-column-level-lineage.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-05-reverse-lineage.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-06-config-file-support.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-06-graph-lineage.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-06-unify-single-multi-query.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-07-sample-data-model.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-07-sql-templating.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-08-tables-command.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-09-graph-query-paths.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-13-dissect-command.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2025-12-14-tables-pull-command.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-25-fix-union-lineage-chain.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-26-file-scoped-schema-context.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-28-sparksql-table-extraction.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-29-no-star-flag.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-29-resolve-schema.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-29-schema-pruning-optimization.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-01-29-tables-scrape-command.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/plans/2026-02-02-diagram-output-formats.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/README.md +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/expire_dim_customer.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/load_fact_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/load_fact_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/merge_dim_customer.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/merge_dim_product.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/business/update_dim_customer_metrics.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/complex/conditional_merge.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/complex/cte_insert.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/complex/multi_table_transform.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/dim_customer.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/dim_product.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/fact_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/fact_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_addresses.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_customers.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_order_items.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/raw_products.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/stg_customers.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/stg_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/stg_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/ddl/stg_products.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/incremental/incr_fact_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/incremental/incr_fact_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/incremental/incr_pres_sales_summary.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/maintenance/delete_expired_customers.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/maintenance/update_product_status.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/presentation/load_pres_customer_360.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/presentation/load_pres_customer_cohort.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/presentation/load_pres_product_performance.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/presentation/load_pres_sales_summary.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/staging/load_stg_customers.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/staging/load_stg_orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/staging/load_stg_payments.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sample_data_model/staging/load_stg_products.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/sqlglider.toml.example +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/catalog/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/catalog/base.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/catalog/databricks.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/catalog/registry.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/dissection/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/dissection/analyzer.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/dissection/formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/dissection/models.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/global_models.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/builder.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/merge.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/models.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/query.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/graph/serialization.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/lineage/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/lineage/analyzer.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/lineage/formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/schema/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/schema/extractor.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/templating/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/templating/base.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/templating/jinja.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/templating/registry.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/templating/variables.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/utils/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/utils/config.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/utils/file_utils.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/src/sqlglider/utils/schema.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/analytics_pipeline.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/analytics_pipeline_union_merge.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/customers.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/orders.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/reports.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/multi_file_queries/view_based_merge.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_cte.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_cte_query.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_cte_view_star.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_generated_column_query.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_multi.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_multi_query.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_single_query.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_subquery.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_tables.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_view.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/original_queries/test_view_window_cte.sql +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/fixtures/sample_manifest.csv +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/catalog/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/catalog/test_base.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/catalog/test_databricks.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/catalog/test_registry.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/dissection/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/dissection/test_analyzer.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/dissection/test_formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/dissection/test_models.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_builder.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_merge.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_models.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_query.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/graph/test_serialization.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/lineage/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/lineage/test_analyzer.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/lineage/test_formatters.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/schema/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/schema/test_extractor.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/templating/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/templating/test_base.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/templating/test_jinja.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/templating/test_registry.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/templating/test_variables.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/test_cli.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/utils/__init__.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/utils/test_config.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/utils/test_file_utils.py +0 -0
- {sql_glider-0.1.21 → sql_glider-0.1.24}/tests/sqlglider/utils/test_schema.py +0 -0
|
@@ -276,17 +276,26 @@ uv run sqlglider graph query graph.json --upstream orders.total -f mermaid
|
|
|
276
276
|
# Query with DOT (Graphviz) diagram output
|
|
277
277
|
uv run sqlglider graph query graph.json --downstream customers.id -f dot
|
|
278
278
|
|
|
279
|
+
# Query with Plotly JSON output (for Dash/Plotly apps)
|
|
280
|
+
uv run sqlglider graph query graph.json --upstream orders.total -f plotly
|
|
281
|
+
|
|
279
282
|
# Visualize entire graph as Mermaid diagram
|
|
280
283
|
uv run sqlglider graph visualize graph.json
|
|
281
284
|
|
|
282
285
|
# Visualize entire graph as DOT diagram
|
|
283
286
|
uv run sqlglider graph visualize graph.json -f dot
|
|
284
287
|
|
|
288
|
+
# Visualize entire graph as Plotly JSON
|
|
289
|
+
uv run sqlglider graph visualize graph.json -f plotly
|
|
290
|
+
|
|
285
291
|
# Save diagram to file
|
|
286
292
|
uv run sqlglider graph visualize graph.json -o lineage.mmd
|
|
287
293
|
uv run sqlglider graph visualize graph.json -f dot -o lineage.dot
|
|
294
|
+
uv run sqlglider graph visualize graph.json -f plotly -o lineage.json
|
|
288
295
|
```
|
|
289
296
|
|
|
297
|
+
**Note:** Plotly output requires the optional dependency: `pip install sql-glider[plotly]`
|
|
298
|
+
|
|
290
299
|
### SQL Templating
|
|
291
300
|
|
|
292
301
|
SQL Glider supports Jinja2 templating for SQL files. This allows you to use variables, conditionals, and loops in your SQL before analysis.
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sql-glider
|
|
3
|
+
Version: 0.1.24
|
|
4
|
+
Summary: SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
|
|
5
|
+
Project-URL: Homepage, https://github.com/rycowhi/sql-glider/
|
|
6
|
+
Project-URL: Repository, https://github.com/rycowhi/sql-glider/
|
|
7
|
+
Project-URL: Documentation, https://github.com/rycowhi/sql-glider/
|
|
8
|
+
Project-URL: Issues, https://github.com/rycowhi/sql-glider/issues
|
|
9
|
+
Author-email: Ryan Whitcomb <ryankwhitcomb@gmail.com>
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: data-governance,data-lineage,lineage,sql,sqlglot
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: SQL
|
|
19
|
+
Classifier: Topic :: Database
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: jinja2>=3.0.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Requires-Dist: rich>=13.0.0
|
|
26
|
+
Requires-Dist: rustworkx>=0.15.0
|
|
27
|
+
Requires-Dist: sqlglot[rs]>=25.0.0
|
|
28
|
+
Requires-Dist: typer>=0.9.0
|
|
29
|
+
Provides-Extra: databricks
|
|
30
|
+
Requires-Dist: databricks-sdk>=0.20.0; extra == 'databricks'
|
|
31
|
+
Provides-Extra: plotly
|
|
32
|
+
Requires-Dist: plotly>=5.0.0; extra == 'plotly'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
1
35
|
# SQL Glider
|
|
2
36
|
|
|
3
37
|

|
|
@@ -388,12 +422,33 @@ uv run sqlglider graph query graph.json --upstream orders.customer_id -f mermaid
|
|
|
388
422
|
# Query with DOT (Graphviz) diagram output
|
|
389
423
|
uv run sqlglider graph query graph.json --downstream customers.id -f dot
|
|
390
424
|
|
|
425
|
+
# Query with Plotly JSON output (for interactive visualization)
|
|
426
|
+
uv run sqlglider graph query graph.json --upstream orders.customer_id -f plotly
|
|
427
|
+
|
|
391
428
|
# Visualize entire graph as a diagram
|
|
392
429
|
uv run sqlglider graph visualize graph.json # Mermaid (default)
|
|
393
430
|
uv run sqlglider graph visualize graph.json -f dot # DOT/Graphviz
|
|
431
|
+
uv run sqlglider graph visualize graph.json -f plotly # Plotly JSON
|
|
394
432
|
uv run sqlglider graph visualize graph.json -o lineage.mmd # Save to file
|
|
395
433
|
```
|
|
396
434
|
|
|
435
|
+
> **Note:** Plotly output requires an optional dependency. Install with: `pip install sql-glider[plotly]`
|
|
436
|
+
|
|
437
|
+
The Plotly JSON output can be loaded into Plotly/Dash applications for interactive visualization:
|
|
438
|
+
|
|
439
|
+
```python
|
|
440
|
+
import plotly.io as pio
|
|
441
|
+
from dash import Dash, dcc, html
|
|
442
|
+
|
|
443
|
+
# Load the JSON output
|
|
444
|
+
with open("lineage.json") as f:
|
|
445
|
+
fig = pio.from_json(f.read())
|
|
446
|
+
|
|
447
|
+
# Use in a Dash app
|
|
448
|
+
app = Dash(__name__)
|
|
449
|
+
app.layout = html.Div([dcc.Graph(figure=fig)])
|
|
450
|
+
```
|
|
451
|
+
|
|
397
452
|
**Example Upstream Query Output:**
|
|
398
453
|
```
|
|
399
454
|
Sources for 'order_totals.total'
|
|
@@ -679,12 +734,24 @@ Arguments:
|
|
|
679
734
|
Options:
|
|
680
735
|
--upstream, -u Find source columns for this column [optional]
|
|
681
736
|
--downstream, -d Find affected columns for this source [optional]
|
|
682
|
-
--output-format, -f Output format: 'text', 'json', or '
|
|
737
|
+
--output-format, -f Output format: 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', 'dot', or 'plotly' [default: text]
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
```
|
|
741
|
+
sqlglider graph visualize <graph_file> [OPTIONS]
|
|
742
|
+
|
|
743
|
+
Arguments:
|
|
744
|
+
graph_file Path to graph JSON file [required]
|
|
745
|
+
|
|
746
|
+
Options:
|
|
747
|
+
--output-format, -f Diagram format: 'mermaid', 'mermaid-markdown', 'dot', or 'plotly' [default: mermaid]
|
|
748
|
+
--output-file, -o Write diagram to file instead of stdout [optional]
|
|
683
749
|
```
|
|
684
750
|
|
|
685
751
|
**Notes:**
|
|
686
752
|
- `--upstream` and `--downstream` are mutually exclusive. Use one or the other.
|
|
687
753
|
- Graph queries are case-insensitive for column matching.
|
|
754
|
+
- Plotly output requires optional dependency: `pip install sql-glider[plotly]`
|
|
688
755
|
|
|
689
756
|
## Output Formats
|
|
690
757
|
|
|
@@ -889,6 +956,21 @@ UV_PUBLISH_TOKEN=pypi-...
|
|
|
889
956
|
- **pydantic:** Data validation and serialization
|
|
890
957
|
- **rustworkx:** High-performance graph library for cross-file lineage analysis
|
|
891
958
|
|
|
959
|
+
### Optional Dependencies
|
|
960
|
+
|
|
961
|
+
Install optional features with extras:
|
|
962
|
+
|
|
963
|
+
```bash
|
|
964
|
+
# Databricks catalog integration
|
|
965
|
+
pip install sql-glider[databricks]
|
|
966
|
+
|
|
967
|
+
# Plotly interactive visualization
|
|
968
|
+
pip install sql-glider[plotly]
|
|
969
|
+
|
|
970
|
+
# Install multiple extras
|
|
971
|
+
pip install sql-glider[databricks,plotly]
|
|
972
|
+
```
|
|
973
|
+
|
|
892
974
|
## References
|
|
893
975
|
|
|
894
976
|
- [SQLGlot Documentation](https://sqlglot.com/)
|
|
@@ -1,35 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: sql-glider
|
|
3
|
-
Version: 0.1.21
|
|
4
|
-
Summary: SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
|
|
5
|
-
Project-URL: Homepage, https://github.com/rycowhi/sql-glider/
|
|
6
|
-
Project-URL: Repository, https://github.com/rycowhi/sql-glider/
|
|
7
|
-
Project-URL: Documentation, https://github.com/rycowhi/sql-glider/
|
|
8
|
-
Project-URL: Issues, https://github.com/rycowhi/sql-glider/issues
|
|
9
|
-
Author-email: Ryan Whitcomb <ryankwhitcomb@gmail.com>
|
|
10
|
-
License-Expression: Apache-2.0
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Keywords: data-governance,data-lineage,lineage,sql,sqlglot
|
|
13
|
-
Classifier: Development Status :: 3 - Alpha
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
-
Classifier: Operating System :: OS Independent
|
|
17
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: SQL
|
|
19
|
-
Classifier: Topic :: Database
|
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Classifier: Typing :: Typed
|
|
22
|
-
Requires-Python: >=3.11
|
|
23
|
-
Requires-Dist: jinja2>=3.0.0
|
|
24
|
-
Requires-Dist: pydantic>=2.0.0
|
|
25
|
-
Requires-Dist: rich>=13.0.0
|
|
26
|
-
Requires-Dist: rustworkx>=0.15.0
|
|
27
|
-
Requires-Dist: sqlglot[rs]>=25.0.0
|
|
28
|
-
Requires-Dist: typer>=0.9.0
|
|
29
|
-
Provides-Extra: databricks
|
|
30
|
-
Requires-Dist: databricks-sdk>=0.20.0; extra == 'databricks'
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
|
|
33
1
|
# SQL Glider
|
|
34
2
|
|
|
35
3
|

|
|
@@ -420,12 +388,33 @@ uv run sqlglider graph query graph.json --upstream orders.customer_id -f mermaid
|
|
|
420
388
|
# Query with DOT (Graphviz) diagram output
|
|
421
389
|
uv run sqlglider graph query graph.json --downstream customers.id -f dot
|
|
422
390
|
|
|
391
|
+
# Query with Plotly JSON output (for interactive visualization)
|
|
392
|
+
uv run sqlglider graph query graph.json --upstream orders.customer_id -f plotly
|
|
393
|
+
|
|
423
394
|
# Visualize entire graph as a diagram
|
|
424
395
|
uv run sqlglider graph visualize graph.json # Mermaid (default)
|
|
425
396
|
uv run sqlglider graph visualize graph.json -f dot # DOT/Graphviz
|
|
397
|
+
uv run sqlglider graph visualize graph.json -f plotly # Plotly JSON
|
|
426
398
|
uv run sqlglider graph visualize graph.json -o lineage.mmd # Save to file
|
|
427
399
|
```
|
|
428
400
|
|
|
401
|
+
> **Note:** Plotly output requires an optional dependency. Install with: `pip install sql-glider[plotly]`
|
|
402
|
+
|
|
403
|
+
The Plotly JSON output can be loaded into Plotly/Dash applications for interactive visualization:
|
|
404
|
+
|
|
405
|
+
```python
|
|
406
|
+
import plotly.io as pio
|
|
407
|
+
from dash import Dash, dcc, html
|
|
408
|
+
|
|
409
|
+
# Load the JSON output
|
|
410
|
+
with open("lineage.json") as f:
|
|
411
|
+
fig = pio.from_json(f.read())
|
|
412
|
+
|
|
413
|
+
# Use in a Dash app
|
|
414
|
+
app = Dash(__name__)
|
|
415
|
+
app.layout = html.Div([dcc.Graph(figure=fig)])
|
|
416
|
+
```
|
|
417
|
+
|
|
429
418
|
**Example Upstream Query Output:**
|
|
430
419
|
```
|
|
431
420
|
Sources for 'order_totals.total'
|
|
@@ -711,12 +700,24 @@ Arguments:
|
|
|
711
700
|
Options:
|
|
712
701
|
--upstream, -u Find source columns for this column [optional]
|
|
713
702
|
--downstream, -d Find affected columns for this source [optional]
|
|
714
|
-
--output-format, -f Output format: 'text', 'json', or '
|
|
703
|
+
--output-format, -f Output format: 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', 'dot', or 'plotly' [default: text]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
```
|
|
707
|
+
sqlglider graph visualize <graph_file> [OPTIONS]
|
|
708
|
+
|
|
709
|
+
Arguments:
|
|
710
|
+
graph_file Path to graph JSON file [required]
|
|
711
|
+
|
|
712
|
+
Options:
|
|
713
|
+
--output-format, -f Diagram format: 'mermaid', 'mermaid-markdown', 'dot', or 'plotly' [default: mermaid]
|
|
714
|
+
--output-file, -o Write diagram to file instead of stdout [optional]
|
|
715
715
|
```
|
|
716
716
|
|
|
717
717
|
**Notes:**
|
|
718
718
|
- `--upstream` and `--downstream` are mutually exclusive. Use one or the other.
|
|
719
719
|
- Graph queries are case-insensitive for column matching.
|
|
720
|
+
- Plotly output requires optional dependency: `pip install sql-glider[plotly]`
|
|
720
721
|
|
|
721
722
|
## Output Formats
|
|
722
723
|
|
|
@@ -921,6 +922,21 @@ UV_PUBLISH_TOKEN=pypi-...
|
|
|
921
922
|
- **pydantic:** Data validation and serialization
|
|
922
923
|
- **rustworkx:** High-performance graph library for cross-file lineage analysis
|
|
923
924
|
|
|
925
|
+
### Optional Dependencies
|
|
926
|
+
|
|
927
|
+
Install optional features with extras:
|
|
928
|
+
|
|
929
|
+
```bash
|
|
930
|
+
# Databricks catalog integration
|
|
931
|
+
pip install sql-glider[databricks]
|
|
932
|
+
|
|
933
|
+
# Plotly interactive visualization
|
|
934
|
+
pip install sql-glider[plotly]
|
|
935
|
+
|
|
936
|
+
# Install multiple extras
|
|
937
|
+
pip install sql-glider[databricks,plotly]
|
|
938
|
+
```
|
|
939
|
+
|
|
924
940
|
## References
|
|
925
941
|
|
|
926
942
|
- [SQLGlot Documentation](https://sqlglot.com/)
|
|
@@ -221,7 +221,7 @@ Each entry in `columns` tells you:
|
|
|
221
221
|
|
|
222
222
|
## Visualizing Lineage
|
|
223
223
|
|
|
224
|
-
SQL Glider can generate diagrams from lineage graphs in [Mermaid](https://mermaid.js.org/)
|
|
224
|
+
SQL Glider can generate diagrams from lineage graphs in [Mermaid](https://mermaid.js.org/), [DOT (Graphviz)](https://graphviz.org/doc/info/lang.html), and [Plotly](https://plotly.com/python/) formats. Mermaid and DOT are text-based diagram languages that render in many tools — Mermaid works natively in GitHub Markdown, GitLab, Notion, and more; DOT can be rendered with Graphviz into SVG, PNG, or PDF. Plotly outputs JSON that can be loaded into interactive Plotly/Dash applications.
|
|
225
225
|
|
|
226
226
|
### Visualize an Entire Graph
|
|
227
227
|
|
|
@@ -234,9 +234,13 @@ sqlglider graph visualize graph.json
|
|
|
234
234
|
# DOT (Graphviz)
|
|
235
235
|
sqlglider graph visualize graph.json -f dot
|
|
236
236
|
|
|
237
|
+
# Plotly JSON (for interactive visualization)
|
|
238
|
+
sqlglider graph visualize graph.json -f plotly
|
|
239
|
+
|
|
237
240
|
# Save to file
|
|
238
241
|
sqlglider graph visualize graph.json -o lineage.mmd
|
|
239
242
|
sqlglider graph visualize graph.json -f dot -o lineage.dot
|
|
243
|
+
sqlglider graph visualize graph.json -f plotly -o lineage.json
|
|
240
244
|
```
|
|
241
245
|
|
|
242
246
|
### Diagram Output from Queries
|
|
@@ -249,6 +253,9 @@ sqlglider graph query graph.json --upstream total_spent -f mermaid
|
|
|
249
253
|
|
|
250
254
|
# DOT diagram of downstream impact
|
|
251
255
|
sqlglider graph query graph.json --downstream orders.order_total -f dot
|
|
256
|
+
|
|
257
|
+
# Plotly JSON for interactive exploration
|
|
258
|
+
sqlglider graph query graph.json --upstream total_spent -f plotly
|
|
252
259
|
```
|
|
253
260
|
|
|
254
261
|
Query diagrams include color-coded nodes and a legend:
|
|
@@ -308,6 +315,47 @@ sqlglider graph visualize graph.json -f mermaid-markdown -o lineage.md
|
|
|
308
315
|
|
|
309
316
|
This produces output with the `` ```mermaid `` fence included, so the diagram renders automatically when viewed in GitHub, GitLab, or any markdown tool with Mermaid support.
|
|
310
317
|
|
|
318
|
+
### Plotly Interactive Visualization
|
|
319
|
+
|
|
320
|
+
The `plotly` format outputs a JSON figure specification that can be loaded into [Plotly](https://plotly.com/python/) or [Dash](https://dash.plotly.com/) applications for interactive visualization with zooming, panning, and hover details.
|
|
321
|
+
|
|
322
|
+
!!! warning "Optional Dependency"
|
|
323
|
+
|
|
324
|
+
Plotly output requires an optional dependency. Install it with:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
pip install sql-glider[plotly]
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Example usage with Dash:**
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
import plotly.io as pio
|
|
334
|
+
from dash import Dash, dcc, html
|
|
335
|
+
|
|
336
|
+
# Load the JSON output from sqlglider
|
|
337
|
+
with open("lineage.json") as f:
|
|
338
|
+
fig = pio.from_json(f.read())
|
|
339
|
+
|
|
340
|
+
# Create an interactive Dash app
|
|
341
|
+
app = Dash(__name__)
|
|
342
|
+
app.layout = html.Div([
|
|
343
|
+
html.H1("Lineage Graph"),
|
|
344
|
+
dcc.Graph(figure=fig, style={"height": "80vh"})
|
|
345
|
+
])
|
|
346
|
+
|
|
347
|
+
if __name__ == "__main__":
|
|
348
|
+
app.run(debug=True)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The Plotly output uses the same color scheme as Mermaid and DOT diagrams:
|
|
352
|
+
|
|
353
|
+
| Color | Meaning |
|
|
354
|
+
|--------|---------|
|
|
355
|
+
| Amber | The queried column |
|
|
356
|
+
| Teal | Root node (no upstream dependencies) |
|
|
357
|
+
| Violet | Leaf node (no downstream consumers) |
|
|
358
|
+
|
|
311
359
|
### Rendering Diagrams
|
|
312
360
|
|
|
313
361
|
**Mermaid:**
|
|
@@ -322,6 +370,12 @@ This produces output with the `` ```mermaid `` fence included, so the diagram re
|
|
|
322
370
|
- Use `-Tsvg` for scalable vector output
|
|
323
371
|
- Many IDEs have Graphviz preview extensions
|
|
324
372
|
|
|
373
|
+
**Plotly:**
|
|
374
|
+
|
|
375
|
+
- Load the JSON into any Plotly-compatible environment (Python, Dash, Jupyter notebooks)
|
|
376
|
+
- SQL Glider includes a viewer script: `python examples/plotly_viewer.py lineage.json`
|
|
377
|
+
- Export to static images with `fig.write_image("lineage.png")`
|
|
378
|
+
|
|
325
379
|
## Building Graphs from Multiple Sources
|
|
326
380
|
|
|
327
381
|
### Explicit File List
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
# ============================================================================
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
|
+
repo_url = "https://github.com/rycowhi/sql-glider/"
|
|
11
|
+
repo_name = "rycowhi/sql-glider"
|
|
10
12
|
|
|
11
13
|
# The site_name is shown in the page header and the browser window title
|
|
12
14
|
#
|
|
@@ -292,15 +294,15 @@ toggle.name = "Switch to dark mode"
|
|
|
292
294
|
# - https://zensical.org/docs/setup/logo-and-icons
|
|
293
295
|
# - https://zensical.org/docs/authoring/icons-emojis/#search
|
|
294
296
|
# ----------------------------------------------------------------------------
|
|
295
|
-
|
|
297
|
+
[project.theme.icon]
|
|
296
298
|
#logo = "lucide/smile"
|
|
297
|
-
|
|
299
|
+
repo = "fontawesome/brands/github"
|
|
298
300
|
|
|
299
301
|
# ----------------------------------------------------------------------------
|
|
300
302
|
# The "extra" section contains miscellaneous settings.
|
|
301
303
|
# ----------------------------------------------------------------------------
|
|
302
|
-
|
|
304
|
+
[[project.extra.social]]
|
|
303
305
|
icon = "fontawesome/brands/github"
|
|
304
|
-
link = "https://github.com/rycowhi/sql-glider/
|
|
306
|
+
link = "https://github.com/rycowhi/sql-glider/"
|
|
305
307
|
|
|
306
308
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Simple Dash app to view SQL Glider Plotly lineage output.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
# graph visualize has -o flag for file output
|
|
6
|
+
uv run sqlglider graph visualize graph.json -f plotly -o lineage.json
|
|
7
|
+
uv run python examples/plotly_viewer.py lineage.json
|
|
8
|
+
|
|
9
|
+
# graph query needs shell redirect - use PowerShell on Windows for proper encoding
|
|
10
|
+
uv run sqlglider graph query graph.json --upstream orders.total -f plotly | Out-File -Encoding utf8 lineage.json
|
|
11
|
+
uv run python examples/plotly_viewer.py lineage.json
|
|
12
|
+
|
|
13
|
+
# On Unix/macOS:
|
|
14
|
+
sqlglider graph query graph.json --upstream orders.total -f plotly > lineage.json
|
|
15
|
+
python examples/plotly_viewer.py lineage.json
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import sys
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
import dash
|
|
24
|
+
from dash import dcc, html
|
|
25
|
+
except ImportError:
|
|
26
|
+
print("Error: Dash is required. Install with: pip install dash", file=sys.stderr)
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_figure(source: str | Path | None = None) -> dict:
|
|
31
|
+
"""Load Plotly figure from file or stdin."""
|
|
32
|
+
if source is None or source == "-":
|
|
33
|
+
# Read from stdin
|
|
34
|
+
if sys.stdin.isatty():
|
|
35
|
+
print("Usage: python plotly_viewer.py <lineage.json>", file=sys.stderr)
|
|
36
|
+
print(" or: sqlglider graph visualize graph.json -f plotly | python plotly_viewer.py", file=sys.stderr)
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
content = sys.stdin.read()
|
|
39
|
+
if not content.strip():
|
|
40
|
+
print("Error: No input received from stdin", file=sys.stderr)
|
|
41
|
+
print("Note: On Windows, piping may not work reliably.", file=sys.stderr)
|
|
42
|
+
print("Try: sqlglider graph query ... -f plotly -o output.json", file=sys.stderr)
|
|
43
|
+
print("Then: python plotly_viewer.py output.json", file=sys.stderr)
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
else:
|
|
46
|
+
path = Path(source)
|
|
47
|
+
if not path.exists():
|
|
48
|
+
print(f"Error: File not found: {path}", file=sys.stderr)
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
# Try multiple encodings - Windows redirect can create UTF-16 files
|
|
51
|
+
for encoding in ["utf-8", "utf-16", "utf-8-sig"]:
|
|
52
|
+
try:
|
|
53
|
+
content = path.read_text(encoding=encoding)
|
|
54
|
+
break
|
|
55
|
+
except UnicodeDecodeError:
|
|
56
|
+
continue
|
|
57
|
+
else:
|
|
58
|
+
print(f"Error: Could not decode file with UTF-8 or UTF-16 encoding", file=sys.stderr)
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
return json.loads(content)
|
|
63
|
+
except json.JSONDecodeError as e:
|
|
64
|
+
print(f"Error: Invalid JSON: {e}", file=sys.stderr)
|
|
65
|
+
if len(content) < 200:
|
|
66
|
+
print(f"Content received: {content!r}", file=sys.stderr)
|
|
67
|
+
else:
|
|
68
|
+
print(f"Content starts with: {content[:200]!r}...", file=sys.stderr)
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def create_app(figure: dict) -> dash.Dash:
|
|
73
|
+
"""Create Dash app with the lineage graph."""
|
|
74
|
+
app = dash.Dash(__name__)
|
|
75
|
+
|
|
76
|
+
title = figure.get("layout", {}).get("title", {}).get("text", "Lineage Graph")
|
|
77
|
+
|
|
78
|
+
app.layout = html.Div(
|
|
79
|
+
[
|
|
80
|
+
html.H1(title, style={"textAlign": "center", "fontFamily": "sans-serif"}),
|
|
81
|
+
dcc.Graph(
|
|
82
|
+
id="lineage-graph",
|
|
83
|
+
figure=figure,
|
|
84
|
+
style={"height": "85vh"},
|
|
85
|
+
config={
|
|
86
|
+
"displayModeBar": True,
|
|
87
|
+
"scrollZoom": True,
|
|
88
|
+
"modeBarButtonsToAdd": ["select2d", "lasso2d"],
|
|
89
|
+
},
|
|
90
|
+
),
|
|
91
|
+
],
|
|
92
|
+
style={"padding": "20px"},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return app
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def main():
|
|
99
|
+
source = sys.argv[1] if len(sys.argv) > 1 else None
|
|
100
|
+
figure = load_figure(source)
|
|
101
|
+
app = create_app(figure)
|
|
102
|
+
|
|
103
|
+
print("Starting Dash server at http://127.0.0.1:8050")
|
|
104
|
+
print("Press Ctrl+C to stop")
|
|
105
|
+
app.run(debug=True, host="127.0.0.1", port=8050)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
main()
|
|
@@ -35,6 +35,7 @@ dependencies = [
|
|
|
35
35
|
|
|
36
36
|
[project.optional-dependencies]
|
|
37
37
|
databricks = ["databricks-sdk>=0.20.0"]
|
|
38
|
+
plotly = ["plotly>=5.0.0"]
|
|
38
39
|
|
|
39
40
|
[project.urls]
|
|
40
41
|
Homepage = "https://github.com/rycowhi/sql-glider/"
|
|
@@ -67,7 +68,9 @@ package = true
|
|
|
67
68
|
[dependency-groups]
|
|
68
69
|
dev = [
|
|
69
70
|
"basedpyright>=1.36.0",
|
|
71
|
+
"dash>=3.4.0",
|
|
70
72
|
"databricks-sdk>=0.20.0", # For testing catalog integration
|
|
73
|
+
"plotly>=6.5.2",
|
|
71
74
|
"pytest>=9.0.1",
|
|
72
75
|
"pytest-cov>=7.0.0",
|
|
73
76
|
"pytest-mock>=3.15.1",
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.1.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
31
|
+
__version__ = version = '0.1.24'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 24)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -1642,7 +1642,7 @@ def graph_query(
|
|
|
1642
1642
|
"text",
|
|
1643
1643
|
"--output-format",
|
|
1644
1644
|
"-f",
|
|
1645
|
-
help="Output format: 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', or '
|
|
1645
|
+
help="Output format: 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', 'dot', or 'plotly'",
|
|
1646
1646
|
),
|
|
1647
1647
|
) -> None:
|
|
1648
1648
|
"""
|
|
@@ -1661,6 +1661,9 @@ def graph_query(
|
|
|
1661
1661
|
|
|
1662
1662
|
# CSV output
|
|
1663
1663
|
sqlglider graph query graph.json --downstream orders.order_id -f csv
|
|
1664
|
+
|
|
1665
|
+
# Plotly JSON output (for Dash/Plotly visualization)
|
|
1666
|
+
sqlglider graph query graph.json --upstream orders.total -f plotly
|
|
1664
1667
|
"""
|
|
1665
1668
|
from sqlglider.graph.query import GraphQuerier
|
|
1666
1669
|
|
|
@@ -1678,10 +1681,18 @@ def graph_query(
|
|
|
1678
1681
|
)
|
|
1679
1682
|
raise typer.Exit(1)
|
|
1680
1683
|
|
|
1681
|
-
if output_format not in [
|
|
1684
|
+
if output_format not in [
|
|
1685
|
+
"text",
|
|
1686
|
+
"json",
|
|
1687
|
+
"csv",
|
|
1688
|
+
"mermaid",
|
|
1689
|
+
"mermaid-markdown",
|
|
1690
|
+
"dot",
|
|
1691
|
+
"plotly",
|
|
1692
|
+
]:
|
|
1682
1693
|
err_console.print(
|
|
1683
1694
|
f"[red]Error:[/red] Invalid output format '{output_format}'. "
|
|
1684
|
-
"Use 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', or '
|
|
1695
|
+
"Use 'text', 'json', 'csv', 'mermaid', 'mermaid-markdown', 'dot', or 'plotly'."
|
|
1685
1696
|
)
|
|
1686
1697
|
raise typer.Exit(1)
|
|
1687
1698
|
|
|
@@ -1713,6 +1724,14 @@ def graph_query(
|
|
|
1713
1724
|
from sqlglider.graph.diagram_formatters import DotFormatter
|
|
1714
1725
|
|
|
1715
1726
|
print(DotFormatter.format_query_result(result))
|
|
1727
|
+
elif output_format == "plotly":
|
|
1728
|
+
from sqlglider.graph.diagram_formatters import PlotlyFormatter
|
|
1729
|
+
|
|
1730
|
+
print(PlotlyFormatter.format_query_result(result))
|
|
1731
|
+
|
|
1732
|
+
except ImportError as e:
|
|
1733
|
+
err_console.print(f"[red]Error:[/red] {e}")
|
|
1734
|
+
raise typer.Exit(1)
|
|
1716
1735
|
|
|
1717
1736
|
except FileNotFoundError as e:
|
|
1718
1737
|
err_console.print(f"[red]Error:[/red] {e}")
|
|
@@ -1818,7 +1837,7 @@ def graph_visualize(
|
|
|
1818
1837
|
"mermaid",
|
|
1819
1838
|
"--output-format",
|
|
1820
1839
|
"-f",
|
|
1821
|
-
help="Diagram format: 'mermaid', 'mermaid-markdown', or '
|
|
1840
|
+
help="Diagram format: 'mermaid', 'mermaid-markdown', 'dot', or 'plotly'",
|
|
1822
1841
|
),
|
|
1823
1842
|
output_file: Optional[Path] = typer.Option(
|
|
1824
1843
|
None,
|
|
@@ -1830,8 +1849,8 @@ def graph_visualize(
|
|
|
1830
1849
|
"""
|
|
1831
1850
|
Visualize the entire lineage graph as a diagram.
|
|
1832
1851
|
|
|
1833
|
-
Generates Mermaid
|
|
1834
|
-
in the graph for visualization tools.
|
|
1852
|
+
Generates Mermaid, DOT (Graphviz), or Plotly JSON diagrams showing all
|
|
1853
|
+
nodes and edges in the graph for visualization tools.
|
|
1835
1854
|
|
|
1836
1855
|
Examples:
|
|
1837
1856
|
|
|
@@ -1846,18 +1865,16 @@ def graph_visualize(
|
|
|
1846
1865
|
|
|
1847
1866
|
# Render DOT to PNG with Graphviz
|
|
1848
1867
|
sqlglider graph visualize graph.json -f dot -o lineage.dot
|
|
1868
|
+
|
|
1869
|
+
# Generate Plotly JSON for Dash/Plotly apps
|
|
1870
|
+
sqlglider graph visualize graph.json -f plotly -o lineage.json
|
|
1849
1871
|
"""
|
|
1850
|
-
from sqlglider.graph.diagram_formatters import (
|
|
1851
|
-
DotFormatter,
|
|
1852
|
-
MermaidFormatter,
|
|
1853
|
-
MermaidMarkdownFormatter,
|
|
1854
|
-
)
|
|
1855
1872
|
from sqlglider.graph.serialization import load_graph
|
|
1856
1873
|
|
|
1857
|
-
if output_format not in ["mermaid", "mermaid-markdown", "dot"]:
|
|
1874
|
+
if output_format not in ["mermaid", "mermaid-markdown", "dot", "plotly"]:
|
|
1858
1875
|
err_console.print(
|
|
1859
1876
|
f"[red]Error:[/red] Invalid output format '{output_format}'. "
|
|
1860
|
-
"Use 'mermaid', 'mermaid-markdown', or '
|
|
1877
|
+
"Use 'mermaid', 'mermaid-markdown', 'dot', or 'plotly'."
|
|
1861
1878
|
)
|
|
1862
1879
|
raise typer.Exit(1)
|
|
1863
1880
|
|
|
@@ -1865,20 +1882,32 @@ def graph_visualize(
|
|
|
1865
1882
|
graph = load_graph(graph_file)
|
|
1866
1883
|
|
|
1867
1884
|
if output_format == "mermaid":
|
|
1885
|
+
from sqlglider.graph.diagram_formatters import MermaidFormatter
|
|
1886
|
+
|
|
1868
1887
|
diagram = MermaidFormatter.format_full_graph(graph)
|
|
1869
1888
|
elif output_format == "mermaid-markdown":
|
|
1889
|
+
from sqlglider.graph.diagram_formatters import MermaidMarkdownFormatter
|
|
1890
|
+
|
|
1870
1891
|
diagram = MermaidMarkdownFormatter.format_full_graph(graph)
|
|
1871
|
-
|
|
1892
|
+
elif output_format == "dot":
|
|
1893
|
+
from sqlglider.graph.diagram_formatters import DotFormatter
|
|
1894
|
+
|
|
1872
1895
|
diagram = DotFormatter.format_full_graph(graph)
|
|
1896
|
+
else: # plotly
|
|
1897
|
+
from sqlglider.graph.diagram_formatters import PlotlyFormatter
|
|
1898
|
+
|
|
1899
|
+
diagram = PlotlyFormatter.format_full_graph(graph)
|
|
1873
1900
|
|
|
1874
1901
|
if output_file:
|
|
1875
1902
|
output_file.write_text(diagram, encoding="utf-8")
|
|
1876
|
-
console.print(
|
|
1877
|
-
f"[green]Success:[/green] Diagram written to {output_file}"
|
|
1878
|
-
)
|
|
1903
|
+
console.print(f"[green]Success:[/green] Diagram written to {output_file}")
|
|
1879
1904
|
else:
|
|
1880
1905
|
print(diagram)
|
|
1881
1906
|
|
|
1907
|
+
except ImportError as e:
|
|
1908
|
+
err_console.print(f"[red]Error:[/red] {e}")
|
|
1909
|
+
raise typer.Exit(1)
|
|
1910
|
+
|
|
1882
1911
|
except FileNotFoundError as e:
|
|
1883
1912
|
err_console.print(f"[red]Error:[/red] {e}")
|
|
1884
1913
|
raise typer.Exit(1)
|