sql-glider 0.1.20__tar.gz → 0.1.23__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.
Files changed (161) hide show
  1. sql_glider-0.1.23/.github/workflows/docs.yml +54 -0
  2. {sql_glider-0.1.20 → sql_glider-0.1.23}/.gitignore +2 -1
  3. {sql_glider-0.1.20 → sql_glider-0.1.23}/ARCHITECTURE.md +10 -0
  4. {sql_glider-0.1.20 → sql_glider-0.1.23}/CLAUDE.md +17 -0
  5. {sql_glider-0.1.20 → sql_glider-0.1.23}/PKG-INFO +41 -1
  6. {sql_glider-0.1.20 → sql_glider-0.1.23}/README.md +40 -0
  7. sql_glider-0.1.23/docs/.github/workflows/docs.yml +29 -0
  8. sql_glider-0.1.23/docs/docs/catalogs.md +190 -0
  9. sql_glider-0.1.23/docs/docs/graph-lineage.md +399 -0
  10. sql_glider-0.1.23/docs/docs/index.md +51 -0
  11. sql_glider-0.1.23/docs/docs/static/sqlglider-logo-transparent.png +0 -0
  12. sql_glider-0.1.23/docs/docs/templating.md +235 -0
  13. sql_glider-0.1.23/docs/zensical.toml +308 -0
  14. sql_glider-0.1.23/plans/2026-02-02-diagram-output-formats.md +62 -0
  15. {sql_glider-0.1.20 → sql_glider-0.1.23}/pyproject.toml +4 -1
  16. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/_version.py +2 -2
  17. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/cli.py +106 -4
  18. sql_glider-0.1.23/src/sqlglider/graph/diagram_formatters.py +330 -0
  19. sql_glider-0.1.23/tests/sqlglider/graph/test_diagram_formatters.py +414 -0
  20. {sql_glider-0.1.20 → sql_glider-0.1.23}/uv.lock +63 -0
  21. {sql_glider-0.1.20 → sql_glider-0.1.23}/.github/workflows/ci.yml +0 -0
  22. {sql_glider-0.1.20 → sql_glider-0.1.23}/.github/workflows/publish.yml +0 -0
  23. {sql_glider-0.1.20 → sql_glider-0.1.23}/.python-version +0 -0
  24. {sql_glider-0.1.20 → sql_glider-0.1.23}/LICENSE +0 -0
  25. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-05-column-level-lineage.md +0 -0
  26. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-05-reverse-lineage.md +0 -0
  27. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-06-config-file-support.md +0 -0
  28. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-06-graph-lineage.md +0 -0
  29. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-06-unify-single-multi-query.md +0 -0
  30. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-07-sample-data-model.md +0 -0
  31. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-07-sql-templating.md +0 -0
  32. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-08-tables-command.md +0 -0
  33. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-09-graph-query-paths.md +0 -0
  34. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-13-dissect-command.md +0 -0
  35. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2025-12-14-tables-pull-command.md +0 -0
  36. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-25-fix-union-lineage-chain.md +0 -0
  37. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-26-file-scoped-schema-context.md +0 -0
  38. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-28-sparksql-table-extraction.md +0 -0
  39. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-29-no-star-flag.md +0 -0
  40. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-29-resolve-schema.md +0 -0
  41. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-29-schema-pruning-optimization.md +0 -0
  42. {sql_glider-0.1.20 → sql_glider-0.1.23}/plans/2026-01-29-tables-scrape-command.md +0 -0
  43. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/README.md +0 -0
  44. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/expire_dim_customer.sql +0 -0
  45. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/load_fact_orders.sql +0 -0
  46. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/load_fact_payments.sql +0 -0
  47. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/merge_dim_customer.sql +0 -0
  48. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/merge_dim_product.sql +0 -0
  49. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/business/update_dim_customer_metrics.sql +0 -0
  50. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/complex/conditional_merge.sql +0 -0
  51. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/complex/cte_insert.sql +0 -0
  52. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/complex/multi_table_transform.sql +0 -0
  53. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/dim_customer.sql +0 -0
  54. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/dim_product.sql +0 -0
  55. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/fact_orders.sql +0 -0
  56. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/fact_payments.sql +0 -0
  57. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_addresses.sql +0 -0
  58. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_customers.sql +0 -0
  59. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_order_items.sql +0 -0
  60. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_orders.sql +0 -0
  61. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_payments.sql +0 -0
  62. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/raw_products.sql +0 -0
  63. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/stg_customers.sql +0 -0
  64. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/stg_orders.sql +0 -0
  65. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/stg_payments.sql +0 -0
  66. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/ddl/stg_products.sql +0 -0
  67. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/incremental/incr_fact_orders.sql +0 -0
  68. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/incremental/incr_fact_payments.sql +0 -0
  69. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/incremental/incr_pres_sales_summary.sql +0 -0
  70. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/maintenance/delete_expired_customers.sql +0 -0
  71. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/maintenance/update_product_status.sql +0 -0
  72. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/presentation/load_pres_customer_360.sql +0 -0
  73. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/presentation/load_pres_customer_cohort.sql +0 -0
  74. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/presentation/load_pres_product_performance.sql +0 -0
  75. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/presentation/load_pres_sales_summary.sql +0 -0
  76. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/staging/load_stg_customers.sql +0 -0
  77. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/staging/load_stg_orders.sql +0 -0
  78. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/staging/load_stg_payments.sql +0 -0
  79. {sql_glider-0.1.20 → sql_glider-0.1.23}/sample_data_model/staging/load_stg_products.sql +0 -0
  80. {sql_glider-0.1.20 → sql_glider-0.1.23}/sqlglider.toml.example +0 -0
  81. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/__init__.py +0 -0
  82. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/catalog/__init__.py +0 -0
  83. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/catalog/base.py +0 -0
  84. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/catalog/databricks.py +0 -0
  85. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/catalog/registry.py +0 -0
  86. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/dissection/__init__.py +0 -0
  87. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/dissection/analyzer.py +0 -0
  88. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/dissection/formatters.py +0 -0
  89. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/dissection/models.py +0 -0
  90. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/global_models.py +0 -0
  91. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/__init__.py +0 -0
  92. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/builder.py +0 -0
  93. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/formatters.py +0 -0
  94. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/merge.py +0 -0
  95. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/models.py +0 -0
  96. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/query.py +0 -0
  97. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/graph/serialization.py +0 -0
  98. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/lineage/__init__.py +0 -0
  99. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/lineage/analyzer.py +0 -0
  100. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/lineage/formatters.py +0 -0
  101. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/schema/__init__.py +0 -0
  102. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/schema/extractor.py +0 -0
  103. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/templating/__init__.py +0 -0
  104. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/templating/base.py +0 -0
  105. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/templating/jinja.py +0 -0
  106. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/templating/registry.py +0 -0
  107. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/templating/variables.py +0 -0
  108. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/utils/__init__.py +0 -0
  109. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/utils/config.py +0 -0
  110. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/utils/file_utils.py +0 -0
  111. {sql_glider-0.1.20 → sql_glider-0.1.23}/src/sqlglider/utils/schema.py +0 -0
  112. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/__init__.py +0 -0
  113. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/analytics_pipeline.sql +0 -0
  114. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/analytics_pipeline_union_merge.sql +0 -0
  115. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/customers.sql +0 -0
  116. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/orders.sql +0 -0
  117. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/reports.sql +0 -0
  118. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/multi_file_queries/view_based_merge.sql +0 -0
  119. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_cte.sql +0 -0
  120. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_cte_query.sql +0 -0
  121. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_cte_view_star.sql +0 -0
  122. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_generated_column_query.sql +0 -0
  123. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_multi.sql +0 -0
  124. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_multi_query.sql +0 -0
  125. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_single_query.sql +0 -0
  126. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_subquery.sql +0 -0
  127. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_tables.sql +0 -0
  128. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_view.sql +0 -0
  129. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/original_queries/test_view_window_cte.sql +0 -0
  130. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/fixtures/sample_manifest.csv +0 -0
  131. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/__init__.py +0 -0
  132. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/catalog/__init__.py +0 -0
  133. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/catalog/test_base.py +0 -0
  134. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/catalog/test_databricks.py +0 -0
  135. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/catalog/test_registry.py +0 -0
  136. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/dissection/__init__.py +0 -0
  137. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/dissection/test_analyzer.py +0 -0
  138. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/dissection/test_formatters.py +0 -0
  139. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/dissection/test_models.py +0 -0
  140. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/__init__.py +0 -0
  141. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_builder.py +0 -0
  142. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_formatters.py +0 -0
  143. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_merge.py +0 -0
  144. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_models.py +0 -0
  145. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_query.py +0 -0
  146. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/graph/test_serialization.py +0 -0
  147. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/lineage/__init__.py +0 -0
  148. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/lineage/test_analyzer.py +0 -0
  149. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/lineage/test_formatters.py +0 -0
  150. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/schema/__init__.py +0 -0
  151. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/schema/test_extractor.py +0 -0
  152. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/templating/__init__.py +0 -0
  153. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/templating/test_base.py +0 -0
  154. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/templating/test_jinja.py +0 -0
  155. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/templating/test_registry.py +0 -0
  156. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/templating/test_variables.py +0 -0
  157. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/test_cli.py +0 -0
  158. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/utils/__init__.py +0 -0
  159. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/utils/test_config.py +0 -0
  160. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/utils/test_file_utils.py +0 -0
  161. {sql_glider-0.1.20 → sql_glider-0.1.23}/tests/sqlglider/utils/test_schema.py +0 -0
@@ -0,0 +1,54 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "docs/**"
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+ pages: write
13
+ id-token: write
14
+
15
+ concurrency:
16
+ group: pages
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v4
27
+ with:
28
+ version: "latest"
29
+
30
+ - name: Set up Python
31
+ run: uv python install 3.11
32
+
33
+ - name: Install dependencies
34
+ run: uv sync --group docs
35
+
36
+ - name: Build docs
37
+ run: uv run zensical build
38
+ working-directory: docs
39
+
40
+ - name: Upload Pages artifact
41
+ uses: actions/upload-pages-artifact@v3
42
+ with:
43
+ path: docs/site
44
+
45
+ deploy:
46
+ needs: build
47
+ runs-on: ubuntu-latest
48
+ environment:
49
+ name: github-pages
50
+ url: ${{ steps.deployment.outputs.page_url }}
51
+ steps:
52
+ - name: Deploy to GitHub Pages
53
+ id: deployment
54
+ uses: actions/deploy-pages@v4
@@ -151,8 +151,9 @@ venv.bak/
151
151
  # Rope project settings
152
152
  .ropeproject
153
153
 
154
- # mkdocs documentation
154
+ # Documentation build output
155
155
  /site
156
+ docs/site/
156
157
 
157
158
  # mypy
158
159
  .mypy_cache/
@@ -23,6 +23,7 @@ sql-glider/
23
23
  │ │ ├── builder.py # GraphBuilder for creating graphs from SQL
24
24
  │ │ ├── merge.py # GraphMerger for combining graphs
25
25
  │ │ ├── query.py # GraphQuerier for upstream/downstream analysis
26
+ │ │ ├── diagram_formatters.py # Mermaid and DOT diagram output formatters
26
27
  │ │ └── serialization.py # JSON save/load, rustworkx conversion
27
28
  │ ├── lineage/
28
29
  │ │ ├── __init__.py # Lineage module exports
@@ -447,6 +448,15 @@ sqlglider graph merge --glob "*.json" -o merged.json
447
448
  # Query lineage
448
449
  sqlglider graph query graph.json --upstream orders.customer_id
449
450
  sqlglider graph query graph.json --downstream customers.id -f json
451
+
452
+ # Query with diagram output (Mermaid or DOT)
453
+ sqlglider graph query graph.json --upstream orders.customer_id -f mermaid
454
+ sqlglider graph query graph.json --downstream customers.id -f dot
455
+
456
+ # Visualize entire graph as diagram
457
+ sqlglider graph visualize graph.json # Mermaid (default)
458
+ sqlglider graph visualize graph.json -f dot # DOT/Graphviz
459
+ sqlglider graph visualize graph.json -o lineage.mmd
450
460
  ```
451
461
 
452
462
  ### 5. Dissection Module (`dissection/`)
@@ -67,6 +67,7 @@ src/sqlglider/
67
67
  │ ├── builder.py # Build lineage graphs from SQL files
68
68
  │ ├── merge.py # Merge multiple graphs
69
69
  │ ├── query.py # Query upstream/downstream lineage
70
+ │ ├── diagram_formatters.py # Mermaid and DOT diagram output formatters
70
71
  │ ├── models.py # Graph data models (Pydantic)
71
72
  │ └── serialization.py # JSON save/load for graphs
72
73
  ├── lineage/
@@ -268,6 +269,22 @@ uv run sqlglider graph query graph.json --upstream orders.total -f json
268
269
 
269
270
  # Query with CSV output
270
271
  uv run sqlglider graph query graph.json --downstream customers.id -f csv
272
+
273
+ # Query with Mermaid diagram output
274
+ uv run sqlglider graph query graph.json --upstream orders.total -f mermaid
275
+
276
+ # Query with DOT (Graphviz) diagram output
277
+ uv run sqlglider graph query graph.json --downstream customers.id -f dot
278
+
279
+ # Visualize entire graph as Mermaid diagram
280
+ uv run sqlglider graph visualize graph.json
281
+
282
+ # Visualize entire graph as DOT diagram
283
+ uv run sqlglider graph visualize graph.json -f dot
284
+
285
+ # Save diagram to file
286
+ uv run sqlglider graph visualize graph.json -o lineage.mmd
287
+ uv run sqlglider graph visualize graph.json -f dot -o lineage.dot
271
288
  ```
272
289
 
273
290
  ### SQL Templating
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-glider
3
- Version: 0.1.20
3
+ Version: 0.1.23
4
4
  Summary: SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
5
5
  Project-URL: Homepage, https://github.com/rycowhi/sql-glider/
6
6
  Project-URL: Repository, https://github.com/rycowhi/sql-glider/
@@ -32,8 +32,12 @@ Description-Content-Type: text/markdown
32
32
 
33
33
  # SQL Glider
34
34
 
35
+ ![SQL Glider Logo](./docs/docs/static/sqlglider-logo-transparent.png)
36
+
35
37
  SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
36
38
 
39
+ **[Read the docs](https://rycowhi.github.io/sql-glider/)**
40
+
37
41
  ## Overview
38
42
 
39
43
  SQL Glider provides powerful column-level and table-level lineage analysis for SQL queries using SQLGlot. It operates on standalone SQL files without requiring a full project setup, making it perfect for ad-hoc analysis, data governance, and understanding query dependencies.
@@ -409,6 +413,17 @@ uv run sqlglider graph query graph.json --upstream orders.customer_id
409
413
 
410
414
  # Query downstream dependencies (find all columns affected by a source)
411
415
  uv run sqlglider graph query graph.json --downstream customers.id
416
+
417
+ # Query with Mermaid diagram output
418
+ uv run sqlglider graph query graph.json --upstream orders.customer_id -f mermaid
419
+
420
+ # Query with DOT (Graphviz) diagram output
421
+ uv run sqlglider graph query graph.json --downstream customers.id -f dot
422
+
423
+ # Visualize entire graph as a diagram
424
+ uv run sqlglider graph visualize graph.json # Mermaid (default)
425
+ uv run sqlglider graph visualize graph.json -f dot # DOT/Graphviz
426
+ uv run sqlglider graph visualize graph.json -o lineage.mmd # Save to file
412
427
  ```
413
428
 
414
429
  **Example Upstream Query Output:**
@@ -796,6 +811,31 @@ src/sqlglider/
796
811
  └── file_utils.py # File I/O utilities
797
812
  ```
798
813
 
814
+ ## Documentation
815
+
816
+ Project documentation is built with [Zensical](https://zensical.org/) and lives in the `docs/` directory:
817
+
818
+ ```
819
+ docs/
820
+ ├── zensical.toml # Site configuration (name, theme, features)
821
+ └── docs/ # Markdown content
822
+ └── index.md # Landing page
823
+ ```
824
+
825
+ To preview docs locally:
826
+
827
+ ```bash
828
+ cd docs && uv run zensical serve
829
+ ```
830
+
831
+ To build the static site:
832
+
833
+ ```bash
834
+ cd docs && uv run zensical build
835
+ ```
836
+
837
+ The built site outputs to `docs/site/` (git-ignored). Documentation is automatically deployed to GitHub Pages on pushes to `main` via the `docs.yml` workflow.
838
+
799
839
  ## Publishing
800
840
 
801
841
  SQL Glider is configured for publishing to both TestPyPI and PyPI using `uv`.
@@ -1,7 +1,11 @@
1
1
  # SQL Glider
2
2
 
3
+ ![SQL Glider Logo](./docs/docs/static/sqlglider-logo-transparent.png)
4
+
3
5
  SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
4
6
 
7
+ **[Read the docs](https://rycowhi.github.io/sql-glider/)**
8
+
5
9
  ## Overview
6
10
 
7
11
  SQL Glider provides powerful column-level and table-level lineage analysis for SQL queries using SQLGlot. It operates on standalone SQL files without requiring a full project setup, making it perfect for ad-hoc analysis, data governance, and understanding query dependencies.
@@ -377,6 +381,17 @@ uv run sqlglider graph query graph.json --upstream orders.customer_id
377
381
 
378
382
  # Query downstream dependencies (find all columns affected by a source)
379
383
  uv run sqlglider graph query graph.json --downstream customers.id
384
+
385
+ # Query with Mermaid diagram output
386
+ uv run sqlglider graph query graph.json --upstream orders.customer_id -f mermaid
387
+
388
+ # Query with DOT (Graphviz) diagram output
389
+ uv run sqlglider graph query graph.json --downstream customers.id -f dot
390
+
391
+ # Visualize entire graph as a diagram
392
+ uv run sqlglider graph visualize graph.json # Mermaid (default)
393
+ uv run sqlglider graph visualize graph.json -f dot # DOT/Graphviz
394
+ uv run sqlglider graph visualize graph.json -o lineage.mmd # Save to file
380
395
  ```
381
396
 
382
397
  **Example Upstream Query Output:**
@@ -764,6 +779,31 @@ src/sqlglider/
764
779
  └── file_utils.py # File I/O utilities
765
780
  ```
766
781
 
782
+ ## Documentation
783
+
784
+ Project documentation is built with [Zensical](https://zensical.org/) and lives in the `docs/` directory:
785
+
786
+ ```
787
+ docs/
788
+ ├── zensical.toml # Site configuration (name, theme, features)
789
+ └── docs/ # Markdown content
790
+ └── index.md # Landing page
791
+ ```
792
+
793
+ To preview docs locally:
794
+
795
+ ```bash
796
+ cd docs && uv run zensical serve
797
+ ```
798
+
799
+ To build the static site:
800
+
801
+ ```bash
802
+ cd docs && uv run zensical build
803
+ ```
804
+
805
+ The built site outputs to `docs/site/` (git-ignored). Documentation is automatically deployed to GitHub Pages on pushes to `main` via the `docs.yml` workflow.
806
+
767
807
  ## Publishing
768
808
 
769
809
  SQL Glider is configured for publishing to both TestPyPI and PyPI using `uv`.
@@ -0,0 +1,29 @@
1
+ name: Documentation
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ - main
7
+ permissions:
8
+ contents: read
9
+ pages: write
10
+ id-token: write
11
+ jobs:
12
+ deploy:
13
+ environment:
14
+ name: github-pages
15
+ url: ${{ steps.deployment.outputs.page_url }}
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/configure-pages@v5
19
+ - uses: actions/checkout@v5
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: 3.x
23
+ - run: pip install zensical
24
+ - run: zensical build --clean
25
+ - uses: actions/upload-pages-artifact@v4
26
+ with:
27
+ path: site
28
+ - uses: actions/deploy-pages@v4
29
+ id: deployment
@@ -0,0 +1,190 @@
1
+ ---
2
+ icon: lucide/database
3
+ ---
4
+
5
+ # Catalogs
6
+
7
+ SQL Glider can connect to remote data catalogs to pull DDL definitions for the tables referenced in your SQL. This is useful when you want to enrich lineage analysis with real schema information, validate queries against production table definitions, or simply collect DDL for documentation.
8
+
9
+ ## How It Works
10
+
11
+ The `tables pull` command reads your SQL, extracts the table names, then fetches the `CREATE TABLE` DDL for each one from a remote catalog. CTEs are automatically excluded since they don't exist in any remote catalog.
12
+
13
+ ```bash
14
+ # Pull DDL for all tables referenced in a query
15
+ sqlglider tables pull query.sql --catalog-type databricks
16
+ ```
17
+
18
+ Output:
19
+
20
+ ```sql
21
+ -- Table: my_catalog.my_schema.customers
22
+ CREATE TABLE my_catalog.my_schema.customers (
23
+ customer_id BIGINT,
24
+ name STRING,
25
+ email STRING,
26
+ created_at TIMESTAMP
27
+ )
28
+ USING DELTA;
29
+ ```
30
+
31
+ You can also write each table's DDL to a separate file:
32
+
33
+ ```bash
34
+ sqlglider tables pull query.sql -c databricks -o ./ddl/
35
+ ```
36
+
37
+ This creates one `.sql` file per table in the `./ddl/` directory.
38
+
39
+ ## Built-in: Databricks
40
+
41
+ SQL Glider ships with a Databricks Unity Catalog provider. It requires the Databricks SDK as an optional dependency:
42
+
43
+ ```bash
44
+ pip install sql-glider[databricks]
45
+ ```
46
+
47
+ ### Authentication
48
+
49
+ The Databricks catalog uses the Databricks SDK's unified authentication, which tries the following sources in order:
50
+
51
+ 1. Explicit host and token from `sqlglider.toml`
52
+ 2. Environment variables (`DATABRICKS_HOST`, `DATABRICKS_TOKEN`)
53
+ 3. Databricks CLI profile (`~/.databrickscfg`)
54
+ 4. OAuth M2M via `DATABRICKS_CLIENT_ID` / `DATABRICKS_CLIENT_SECRET`
55
+ 5. Azure CLI or Google Cloud auth for cloud-hosted workspaces
56
+
57
+ A **warehouse ID** is always required. Set it in config or via the `DATABRICKS_WAREHOUSE_ID` environment variable.
58
+
59
+ ### Configuration
60
+
61
+ Configure Databricks in `sqlglider.toml`:
62
+
63
+ ```toml
64
+ [sqlglider]
65
+ catalog_type = "databricks"
66
+
67
+ [sqlglider.catalog.databricks]
68
+ warehouse_id = "abc123def456"
69
+ profile = "my-workspace" # optional: Databricks CLI profile
70
+ host = "https://my.databricks.com" # optional if using profile or env vars
71
+ token = "dapi..." # optional: prefer OAuth or profile instead
72
+ ```
73
+
74
+ Or use environment variables:
75
+
76
+ ```bash
77
+ export DATABRICKS_HOST="https://my.databricks.com"
78
+ export DATABRICKS_TOKEN="dapi..."
79
+ export DATABRICKS_WAREHOUSE_ID="abc123def456"
80
+ ```
81
+
82
+ ### Usage
83
+
84
+ ```bash
85
+ # Pull DDL to stdout
86
+ sqlglider tables pull query.sql -c databricks
87
+
88
+ # Pull DDL to folder
89
+ sqlglider tables pull query.sql -c databricks -o ./ddl/
90
+
91
+ # Combine with templating
92
+ sqlglider tables pull query.sql -c databricks --templater jinja --var schema=prod
93
+
94
+ # From stdin
95
+ echo "SELECT * FROM my_catalog.my_schema.users" | sqlglider tables pull -c databricks
96
+
97
+ # List available catalog providers
98
+ sqlglider tables pull --list
99
+ ```
100
+
101
+ ## Writing a Custom Catalog Provider
102
+
103
+ You can create your own catalog provider as a Python package and register it as a plugin.
104
+
105
+ ### 1. Implement the Catalog Class
106
+
107
+ Subclass `sqlglider.catalog.base.Catalog` and implement three methods:
108
+
109
+ ```python
110
+ from typing import Any, Dict, List, Optional
111
+
112
+ from sqlglider.catalog.base import Catalog, CatalogError
113
+
114
+
115
+ class SnowflakeCatalog(Catalog):
116
+ @property
117
+ def name(self) -> str:
118
+ return "snowflake"
119
+
120
+ def configure(self, config: Optional[Dict[str, Any]] = None) -> None:
121
+ """Set up connection details from config or environment."""
122
+ config = config or {}
123
+ self._account = config.get("account")
124
+ self._warehouse = config.get("warehouse")
125
+ # Validate required settings
126
+ if not self._account:
127
+ raise CatalogError("Snowflake account is required")
128
+
129
+ def get_ddl(self, table_name: str) -> str:
130
+ """Fetch DDL for a single table."""
131
+ try:
132
+ # Connect and run: GET_DDL('TABLE', table_name)
133
+ return ddl_string
134
+ except Exception as e:
135
+ raise CatalogError(f"Failed to fetch DDL for {table_name}: {e}") from e
136
+
137
+ def get_ddl_batch(self, table_names: List[str]) -> Dict[str, str]:
138
+ """Fetch DDL for multiple tables.
139
+
140
+ Return a dict mapping table names to DDL strings.
141
+ For tables that fail, prefix the value with "ERROR: ".
142
+ """
143
+ results: Dict[str, str] = {}
144
+ for table in table_names:
145
+ try:
146
+ results[table] = self.get_ddl(table)
147
+ except CatalogError as e:
148
+ results[table] = f"ERROR: {e}"
149
+ return results
150
+ ```
151
+
152
+ Key points:
153
+
154
+ - **`name`** — the identifier users pass to `--catalog-type`
155
+ - **`configure()`** — called after instantiation with settings from `sqlglider.toml` and CLI; validate required config here
156
+ - **`get_ddl()`** — fetch DDL for one table; raise `CatalogError` on failure
157
+ - **`get_ddl_batch()`** — fetch DDL for many tables; prefix failures with `"ERROR: "` so the batch continues
158
+
159
+ ### 2. Register via Entry Points
160
+
161
+ In your package's `pyproject.toml`:
162
+
163
+ ```toml
164
+ [project.entry-points."sqlglider.catalogs"]
165
+ snowflake = "my_package.catalog:SnowflakeCatalog"
166
+ ```
167
+
168
+ ### 3. Add Configuration Support
169
+
170
+ Users can configure your catalog in `sqlglider.toml`. The config section name matches the catalog name:
171
+
172
+ ```toml
173
+ [sqlglider]
174
+ catalog_type = "snowflake"
175
+
176
+ [sqlglider.catalog.snowflake]
177
+ account = "xy12345.us-east-1"
178
+ warehouse = "COMPUTE_WH"
179
+ ```
180
+
181
+ !!! note
182
+ For the config section to be loaded automatically, the core `ConfigSettings` model needs to know about your provider. For third-party plugins, users can also pass configuration through environment variables in your `configure()` method.
183
+
184
+ ### 4. Use It
185
+
186
+ After installing your package:
187
+
188
+ ```bash
189
+ sqlglider tables pull query.sql --catalog-type snowflake
190
+ ```