sql-code-graph 1.35.1__tar.gz → 1.35.2__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 (612) hide show
  1. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/PKG-INFO +1 -1
  2. sql_code_graph-1.35.2/plan/metrics/pr_c_merge_after.json +31 -0
  3. sql_code_graph-1.35.2/plan/metrics/pr_c_merge_before.json +31 -0
  4. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/pyproject.toml +1 -1
  5. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/__init__.py +1 -1
  6. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/base.py +193 -18
  7. sql_code_graph-1.35.2/src/sqlcg/parsers/dynamic_name.py +170 -0
  8. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_skip_counts_integration.py +12 -10
  9. sql_code_graph-1.35.2/tests/snowflake/E16/test_e16.py +59 -0
  10. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/test_plan_review_gates.py +9 -12
  11. sql_code_graph-1.35.2/tests/unit/test_dynamic_name_resolution.py +148 -0
  12. sql_code_graph-1.35.2/tests/unit/test_merge_column_lineage.py +154 -0
  13. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/uv.lock +1 -1
  14. sql_code_graph-1.35.1/tests/snowflake/E16/test_e16.py +0 -51
  15. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/api-documenter.md +0 -0
  16. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/architect-planner.md +0 -0
  17. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/architect-reviewer.md +0 -0
  18. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/code-reviewer.md +0 -0
  19. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/developer.md +0 -0
  20. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/plan-reviewer.md +0 -0
  21. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.claude/agents/sprint-planner.md +0 -0
  22. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  23. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  25. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/workflows/benchmark.yml +0 -0
  26. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/workflows/e2e-tests.yml +0 -0
  27. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/workflows/release.yml +0 -0
  28. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.github/workflows/test.yml +0 -0
  29. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.gitignore +0 -0
  30. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.pre-commit-config.yaml +0 -0
  31. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/.sqlcgignore +0 -0
  32. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/ARCHITECTURE_REVIEW.md +0 -0
  33. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/ARCHITECTURE_REVIEW_ARCHIVE.md +0 -0
  34. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/CHANGELOG.md +0 -0
  35. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/CLAUDE.md +0 -0
  36. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/README.md +0 -0
  37. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/docs/AIRBNB_PARSE_REPORT.md +0 -0
  38. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/docs/cli.md +0 -0
  39. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/docs/getting-started.md +0 -0
  40. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/docs/releasing-pypi.md +0 -0
  41. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/e2e_firstuser_report.md +0 -0
  42. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/e2e_run_20260528_101413.output +0 -0
  43. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/main.py +0 -0
  44. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/WORKFLOW.md +0 -0
  45. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/pr2_catalog_load_eval.json +0 -0
  46. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/pr3_repo_native_plateau.json +0 -0
  47. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/pr4_transform_kinds.json +0 -0
  48. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/pr5_extraction_recall_taxonomy.json +0 -0
  49. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/sprint_08_changelogs_fullindex.json +0 -0
  50. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/measurements/sprint_08_fullcorpus_index.json +0 -0
  51. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/createkind_dwh_after.json +0 -0
  52. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/createkind_dwh_before.json +0 -0
  53. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/gain_1.29.0_05c6943.json +0 -0
  54. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/gain_1.30.0_2c8ac25.json +0 -0
  55. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/gain_1.30.1_26271fc.json +0 -0
  56. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/gain_1.31.0_a40c837.json +0 -0
  57. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/gain_1.32.0_c1bec3c.json +0 -0
  58. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/lineage5_dwh_after_pr5.json +0 -0
  59. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/lineage5_dwh_before_master.json +0 -0
  60. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/pr4_star_promote_after.json +0 -0
  61. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/pr4_star_promote_before.json +0 -0
  62. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/pr_b_phantom_after.json +0 -0
  63. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/pr_b_phantom_before.json +0 -0
  64. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/schema_comparison_with_schema.json +0 -0
  65. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/schema_comparison_without_schema.json +0 -0
  66. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/sprint_08_changelogs_fullindex.json +0 -0
  67. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/sprint_08_fullcorpus_index.json +0 -0
  68. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/metrics/sprint_pool_300s_plan.json +0 -0
  69. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/column_coverage_diagnostic.md +0 -0
  70. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/column_coverage_findings.md +0 -0
  71. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/dwh_graph_analysis.md +0 -0
  72. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/dwh_positional_insert_column_blindspot.md +0 -0
  73. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/feature_acceptance_dwh.md +0 -0
  74. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/graph_health_sprint_postmortem.md +0 -0
  75. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/island_lever_live_verification.md +0 -0
  76. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/issue38_pr2_live_acceptance.md +0 -0
  77. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/issue38_pr3_live_acceptance.md +0 -0
  78. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/lineage_identity_sprint_postmortem.md +0 -0
  79. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/pr_impact_followups_2026-06-14.md +0 -0
  80. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/sprint_03_v0.3.1_postmortem.md +0 -0
  81. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/sprint_3.1_postmortem.md +0 -0
  82. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/reports/v1_14_dialect_query_config_postmortem.md +0 -0
  83. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/blueprint.md +0 -0
  84. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/coverage_parse_failure_diagnosis.md +0 -0
  85. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/investigation_e5_e4.md +0 -0
  86. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/observed_usage_overlay_query_history_tableau.md +0 -0
  87. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/parse_diagnostics.md +0 -0
  88. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/parsing_errors_experiment.md +0 -0
  89. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/snowflake_en_test_suite.md +0 -0
  90. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/sql_only_coverage_lever_post_pr2.md +0 -0
  91. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/research/sqlcg.md +0 -0
  92. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/bundle_claude_skill.md +0 -0
  93. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/ci_tests_pool_flake_fix.md +0 -0
  94. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/column_lineage_recall_metric.md +0 -0
  95. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/coverage_p1_p3_p4.md +0 -0
  96. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/coverage_p1_p5_metric.md +0 -0
  97. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/coverage_parse_failures.md +0 -0
  98. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/diff-impact-producer-file.md +0 -0
  99. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/e8_dual_emission.md +0 -0
  100. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/feature_34_unused_presentation_segregation.md +0 -0
  101. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/feature_35_external_downstream_injection.md +0 -0
  102. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/feature_F2_bundle_claude_skill.md +0 -0
  103. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/feature_kuzu_to_duckdb_migration.md +0 -0
  104. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_backward_self_heal_index_at_sha.md +0 -0
  105. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_downstream_sink_location.md +0 -0
  106. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_dynamic_table_parsing.md +0 -0
  107. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_expand_qualify_perf.md +0 -0
  108. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_firstuser_findings.md +0 -0
  109. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_issue29_live_test_followups.md +0 -0
  110. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/fix_schema_case_mismatch.md +0 -0
  111. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/gain_coverage_metrics.md +0 -0
  112. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/graph_health_catalog_and_metrics.md +0 -0
  113. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/hygiene_config_path_and_survivors.md +0 -0
  114. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/issue-38-backfill-cte-bridge.md +0 -0
  115. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/issue-38-residual-source-extraction.md +0 -0
  116. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/issue-38-selects-from-island-lever.md +0 -0
  117. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/living_codebase_resync.md +0 -0
  118. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/mcp_server_self_healing.md +0 -0
  119. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/positional_insert_clone_blindspot.md +0 -0
  120. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_01.md +0 -0
  121. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_01_deployment_pypi.md +0 -0
  122. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_02.md +0 -0
  123. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_02_v0.3.0_core.md +0 -0
  124. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_03.md +0 -0
  125. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_04_column_lineage.md +0 -0
  126. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_04_column_lineage_fix.md +0 -0
  127. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_05_star_resolution.md +0 -0
  128. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_06_lineage_coverage.md +0 -0
  129. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_07_open_ecodes.md +0 -0
  130. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_07_perf_and_live_test.md +0 -0
  131. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_08_perf_upsert.md +0 -0
  132. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_09_lineage_coverage.md +0 -0
  133. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_10_anchor_tools.md +0 -0
  134. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_11_v1.0.2_bugfix.md +0 -0
  135. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_12_v1.1.0.md +0 -0
  136. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_13_v1.1.0_cluster_b.md +0 -0
  137. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_lineage_identity_and_session_context.md +0 -0
  138. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/sprint_postmortem_fixes.md +0 -0
  139. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/temp_table_namespacing.md +0 -0
  140. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/trust_layer.md +0 -0
  141. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/unfilled_table_impact.md +0 -0
  142. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1.1.0_cluster_b_provenance_trust.md +0 -0
  143. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1.1.0_live_graph_freshness.md +0 -0
  144. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1.1.1_batch_upsert_perf.md +0 -0
  145. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1.14.0_dialect_and_query_config_fixes.md +0 -0
  146. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1_1_2_bugfix.md +0 -0
  147. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1_1_3_union_cte_star.md +0 -0
  148. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1_2_0_read_proxy.md +0 -0
  149. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/v1_2_1_bugfix.md +0 -0
  150. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/plan/sprints/version-parity-and-restart.md +0 -0
  151. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/profile.html +0 -0
  152. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/pyrightconfig.json +0 -0
  153. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/scripts/collect_parse_errors.py +0 -0
  154. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/scripts/column_coverage_check.py +0 -0
  155. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/scripts/generate_cli_docs.sh +0 -0
  156. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/__main__.py +0 -0
  157. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/__init__.py +0 -0
  158. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/__init__.py +0 -0
  159. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/analyze.py +0 -0
  160. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/catalog.py +0 -0
  161. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/db.py +0 -0
  162. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/find.py +0 -0
  163. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/gain.py +0 -0
  164. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/git.py +0 -0
  165. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/index.py +0 -0
  166. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/install.py +0 -0
  167. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/mcp.py +0 -0
  168. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/reindex.py +0 -0
  169. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/report.py +0 -0
  170. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/uninstall.py +0 -0
  171. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/viz.py +0 -0
  172. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/commands/watch.py +0 -0
  173. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/coverage.py +0 -0
  174. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/cli/main.py +0 -0
  175. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/__init__.py +0 -0
  176. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/config.py +0 -0
  177. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/duckdb_backend.py +0 -0
  178. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/freshness.py +0 -0
  179. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/graph_db.py +0 -0
  180. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/jobs.py +0 -0
  181. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/noise_match.py +0 -0
  182. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/queries.cypher +0 -0
  183. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/queries.py +0 -0
  184. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/queries.sql +0 -0
  185. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/schema.cypher +0 -0
  186. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/core/schema.py +0 -0
  187. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/__init__.py +0 -0
  188. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/dbt_adapter.py +0 -0
  189. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/error_classify.py +0 -0
  190. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/git_delta.py +0 -0
  191. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/indexer.py +0 -0
  192. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/pool.py +0 -0
  193. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/walker.py +0 -0
  194. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/indexer/watcher.py +0 -0
  195. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/lineage/__init__.py +0 -0
  196. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/lineage/aggregator.py +0 -0
  197. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/lineage/schema_resolver.py +0 -0
  198. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/metrics/__init__.py +0 -0
  199. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/metrics/store.py +0 -0
  200. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/__init__.py +0 -0
  201. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/ansi_parser.py +0 -0
  202. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/bigquery_parser.py +0 -0
  203. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/postgres_parser.py +0 -0
  204. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/registry.py +0 -0
  205. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/snowflake_parser.py +0 -0
  206. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/parsers/tsql_parser.py +0 -0
  207. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/__init__.py +0 -0
  208. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/control.py +0 -0
  209. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/exceptions.py +0 -0
  210. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/models.py +0 -0
  211. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/noise_filter.py +0 -0
  212. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/read_client.py +0 -0
  213. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/selfheal.py +0 -0
  214. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/server.py +0 -0
  215. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/skill.py +0 -0
  216. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/tools.py +0 -0
  217. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/server/writer.py +0 -0
  218. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/utils/__init__.py +0 -0
  219. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/utils/hashing.py +0 -0
  220. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/utils/ignore.py +0 -0
  221. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/utils/logging.py +0 -0
  222. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/__init__.py +0 -0
  223. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/assets/force-graph.min.js +0 -0
  224. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/assets/template.html +0 -0
  225. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/data.py +0 -0
  226. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/render.py +0 -0
  227. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/src/sqlcg/viz/tags.py +0 -0
  228. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/__init__.py +0 -0
  229. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/__init__.py +0 -0
  230. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/adversarial/200_join.sql +0 -0
  231. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/adversarial/500_union.sql +0 -0
  232. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/bench_indexer.py +0 -0
  233. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/conftest.py +0 -0
  234. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
  235. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
  236. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
  237. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
  238. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
  239. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
  240. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
  241. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
  242. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
  243. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
  244. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/tpch/q01.sql +0 -0
  245. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/tpch/q02.sql +0 -0
  246. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/tpch/q03.sql +0 -0
  247. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/tpch/q04.sql +0 -0
  248. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/benchmarks/tpch/q05.sql +0 -0
  249. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/conftest.py +0 -0
  250. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/__init__.py +0 -0
  251. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/conftest.py +0 -0
  252. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_F2_skill_install_e2e.py +0 -0
  253. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_airbnb_e2e.py +0 -0
  254. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_cli_index.py +0 -0
  255. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_empty_impact_cli_e2e.py +0 -0
  256. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_git_hook_install.py +0 -0
  257. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_golden_lineage.py +0 -0
  258. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_mcp_lifecycle.py +0 -0
  259. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_mcp_tools.py +0 -0
  260. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
  261. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_pr_impact_cli_e2e.py +0 -0
  262. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_selfheal_e2e.py +0 -0
  263. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_star_resolution_e2e.py +0 -0
  264. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_viz_cli_e2e.py +0 -0
  265. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/e2e/test_watch.py +0 -0
  266. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
  267. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
  268. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
  269. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
  270. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
  271. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/raw_listings.sql +0 -0
  272. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
  273. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/src_hosts.sql +0 -0
  274. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/src_listings.sql +0 -0
  275. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/airbnb/src_reviews.sql +0 -0
  276. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/bigquery/.gitkeep +0 -0
  277. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/duckdb_parity/kuzu_reference.json +0 -0
  278. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/jaffle_shop/customers.sql +0 -0
  279. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/jaffle_shop/orders.sql +0 -0
  280. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
  281. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/snowflake/base_tables.sql +0 -0
  282. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/snowflake/reports.sql +0 -0
  283. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/snowflake/views.sql +0 -0
  284. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
  285. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
  286. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
  287. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/star_corpus/etl_star.sql +0 -0
  288. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/synthetic/base_tables.sql +0 -0
  289. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/synthetic/reports.sql +0 -0
  290. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/fixtures/synthetic/views.sql +0 -0
  291. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/__init__.py +0 -0
  292. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/snowflake/__init__.py +0 -0
  293. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/snowflake/test_insert_select.py +0 -0
  294. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/snowflake/test_qualify_bare_tables_command_guard_integration.py +0 -0
  295. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_T34_presentation_segregation.py +0 -0
  296. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_T35_external_consumers.py +0 -0
  297. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_analyze_case_fold.py +0 -0
  298. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_anchor_tools.py +0 -0
  299. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_backfill_impact_consistency.py +0 -0
  300. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_bare_column_cte_lineage.py +0 -0
  301. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_bulk_upsert.py +0 -0
  302. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_case_split_seed_regression.py +0 -0
  303. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_catalog_kind_upgrade.py +0 -0
  304. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_catalog_load_integration.py +0 -0
  305. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cli_index_clear_before_rebuild.py +0 -0
  306. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_column_coverage_patterns.py +0 -0
  307. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_column_lineage_e2e.py +0 -0
  308. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_coverage_metrics_integration.py +0 -0
  309. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cross_file_lineage.py +0 -0
  310. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cte_key_namespacing_integration.py +0 -0
  311. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cte_recall_guard.py +0 -0
  312. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cte_schema_alias_guard.py +0 -0
  313. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_cte_source_node_invariant.py +0 -0
  314. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_dialect_auto_resolution.py +0 -0
  315. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_dialect_matrix.py +0 -0
  316. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_duckdb_parity.py +0 -0
  317. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_e36_xfile_regression_guard.py +0 -0
  318. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_empty_impact_blast_radius.py +0 -0
  319. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_empty_index_rollback_guard.py +0 -0
  320. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_freshness_mcp.py +0 -0
  321. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_gating_join_retrofit.py +0 -0
  322. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_hygiene_config_root_reconciliation.py +0 -0
  323. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_identity_counters_integration.py +0 -0
  324. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_impact_consumer_parity.py +0 -0
  325. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_index_degraded_files_metric.py +0 -0
  326. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_index_filter_node_exclusion.py +0 -0
  327. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_indexer_batching.py +0 -0
  328. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_indexer_commits.py +0 -0
  329. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_indexer_to_graph.py +0 -0
  330. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_issue38_cte_insert_regression.py +0 -0
  331. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_join_col_resolution.py +0 -0
  332. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_key_normalization_chokepoint.py +0 -0
  333. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_live_anchors.py +0 -0
  334. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_mvcc_rebuild.py +0 -0
  335. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_non_table_create_coverage_no_regression.py +0 -0
  336. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_non_table_create_kind_in_graph.py +0 -0
  337. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_parse_diagnostics.py +0 -0
  338. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_phantom_non_table_create_node.py +0 -0
  339. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_pr1_confidence_reason.py +0 -0
  340. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_pr2_source_location.py +0 -0
  341. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_pr3_kind_tagging.py +0 -0
  342. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_pr_impact_integration.py +0 -0
  343. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_qualify_failed_persist.py +0 -0
  344. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_read_via_server.py +0 -0
  345. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_readonly_under_lock.py +0 -0
  346. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_reindex_via_server.py +0 -0
  347. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_repo_relative_cte_namespaces.py +0 -0
  348. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_resolvable_write_col_edges_integration.py +0 -0
  349. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_resync.py +0 -0
  350. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_selects_from_completeness.py +0 -0
  351. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_selects_from_cte_body_source.py +0 -0
  352. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_selects_from_subscope_source.py +0 -0
  353. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_single_writer_queue.py +0 -0
  354. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_star_promote_temp_columns.py +0 -0
  355. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_star_resolution.py +0 -0
  356. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_temp_table_lineage.py +0 -0
  357. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_temp_table_namespacing.py +0 -0
  358. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_tool_version_stamp_integration.py +0 -0
  359. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_union_cte_star_recall_guard.py +0 -0
  360. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_usage_derived_catalog.py +0 -0
  361. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_use_schema_session_context_integration.py +0 -0
  362. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_user_surface_recall_guard.py +0 -0
  363. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_v141_surface_guards.py +0 -0
  364. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_v1_14_0_dialect_and_query_config_fixes.py +0 -0
  365. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_view_kind_in_graph.py +0 -0
  366. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_viz_data_build.py +0 -0
  367. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/integration/test_write_memory_ceiling.py +0 -0
  368. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/perf/__init__.py +0 -0
  369. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/perf/test_perf.py +0 -0
  370. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E10/__init__.py +0 -0
  371. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E11/__init__.py +0 -0
  372. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E12/__init__.py +0 -0
  373. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E12/e12_json_path.sql +0 -0
  374. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
  375. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E12/test_e12.py +0 -0
  376. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E13/__init__.py +0 -0
  377. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E14/__init__.py +0 -0
  378. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E15/__init__.py +0 -0
  379. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E16/__init__.py +0 -0
  380. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E16/e16_merge.sql +0 -0
  381. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
  382. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E17/__init__.py +0 -0
  383. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E18/__init__.py +0 -0
  384. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E18/e18_decode.sql +0 -0
  385. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
  386. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E18/e18_nvl2.sql +0 -0
  387. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E18/test_e18.py +0 -0
  388. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E19/__init__.py +0 -0
  389. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E2/__init__.py +0 -0
  390. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
  391. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E2/e2_function_alias.sql +0 -0
  392. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
  393. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E2/test_e2.py +0 -0
  394. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E20/__init__.py +0 -0
  395. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E21/__init__.py +0 -0
  396. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
  397. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
  398. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E21/test_e21.py +0 -0
  399. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E22/__init__.py +0 -0
  400. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E23/__init__.py +0 -0
  401. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
  402. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
  403. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E23/test_e23.py +0 -0
  404. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E24/__init__.py +0 -0
  405. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E25/__init__.py +0 -0
  406. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E25/e25_cross_db.sql +0 -0
  407. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E25/e25_two_part.sql +0 -0
  408. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E25/test_e25.py +0 -0
  409. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E25/test_e25_full_id.py +0 -0
  410. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E26/__init__.py +0 -0
  411. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E27/__init__.py +0 -0
  412. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
  413. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E27/e27_udf.sql +0 -0
  414. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E27/test_e27.py +0 -0
  415. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E28/__init__.py +0 -0
  416. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E29/__init__.py +0 -0
  417. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E3/__init__.py +0 -0
  418. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E3/e3_alter_table.sql +0 -0
  419. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
  420. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
  421. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E3/test_e3.py +0 -0
  422. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E30/__init__.py +0 -0
  423. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E31/__init__.py +0 -0
  424. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E32/__init__.py +0 -0
  425. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E33/__init__.py +0 -0
  426. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E34/__init__.py +0 -0
  427. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E35/__init__.py +0 -0
  428. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E36/__init__.py +0 -0
  429. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
  430. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E36/e36_temp_table.sql +0 -0
  431. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E36/test_e36.py +0 -0
  432. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E36/test_e36_xfile.py +0 -0
  433. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E37/__init__.py +0 -0
  434. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E38/__init__.py +0 -0
  435. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/__init__.py +0 -0
  436. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
  437. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
  438. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
  439. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/e4_unpivot.sql +0 -0
  440. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E4/test_e4.py +0 -0
  441. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/__init__.py +0 -0
  442. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
  443. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
  444. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
  445. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/test_e5.py +0 -0
  446. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
  447. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E8/__init__.py +0 -0
  448. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
  449. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
  450. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E8/e8_uuid.sql +0 -0
  451. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E8/test_e8.py +0 -0
  452. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E9/__init__.py +0 -0
  453. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_aggregates/__init__.py +0 -0
  454. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
  455. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
  456. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
  457. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
  458. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/__init__.py +0 -0
  459. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
  460. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
  461. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
  462. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
  463. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
  464. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/README.md +0 -0
  465. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/__init__.py +0 -0
  466. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/__init__.py +0 -0
  467. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/fixture_etl.sql +0 -0
  468. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
  469. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
  470. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/fixture_source.sql +0 -0
  471. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
  472. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
  473. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/snowflake/conftest.py +0 -0
  474. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/__init__.py +0 -0
  475. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/snowflake/__init__.py +0 -0
  476. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/snowflake/test_qualify_bare_tables_command_guard.py +0 -0
  477. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/snowflake/test_scripting_noise.py +0 -0
  478. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_BugB_escalation_uses_init_path.py +0 -0
  479. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_BugC_hook_upgrade.py +0 -0
  480. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_F2_install_skill.py +0 -0
  481. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_F2_skill_render.py +0 -0
  482. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_F2_uninstall_skill.py +0 -0
  483. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_T09_01_qualify_once.py +0 -0
  484. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_T09_02_ddl_skip.py +0 -0
  485. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
  486. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_T09_06_log_verbosity.py +0 -0
  487. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_T35_config_external_consumers.py +0 -0
  488. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_aggregator.py +0 -0
  489. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_aggregator_skip.py +0 -0
  490. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_analyze_case_fold.py +0 -0
  491. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_base_parser.py +0 -0
  492. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_branch_monitor.py +0 -0
  493. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_bulk_upsert_invariant.py +0 -0
  494. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_canonical_target_resolution.py +0 -0
  495. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_catalog_csv_parsing.py +0 -0
  496. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_catalog_missing_warning.py +0 -0
  497. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_classify_non_table_create_kind.py +0 -0
  498. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_cli.py +0 -0
  499. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_cli_doc_flag_staleness.py +0 -0
  500. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_cli_help.py +0 -0
  501. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_clone_positional_insert_blindspot.py +0 -0
  502. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_closure_depth.py +0 -0
  503. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_column_lineage_wiring.py +0 -0
  504. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_config.py +0 -0
  505. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_coverage_metrics.py +0 -0
  506. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_cte_key_namespacing.py +0 -0
  507. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_cte_source_gap_metric.py +0 -0
  508. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_data_models.py +0 -0
  509. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_db_info.py +0 -0
  510. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_db_info_coverage.py +0 -0
  511. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_db_path_isolation_fixture.py +0 -0
  512. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_doc_links.py +0 -0
  513. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_doc_markdown_link_existence.py +0 -0
  514. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_dominant_cause.py +0 -0
  515. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_duckdb_backend.py +0 -0
  516. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_duckdb_backend_shared.py +0 -0
  517. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_e5_view_alias_resolution.py +0 -0
  518. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_e8_dual_emission.py +0 -0
  519. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_e8_temp_chain_key_mismatch.py +0 -0
  520. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_empty_propagation_unit.py +0 -0
  521. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_extract_select_output_columns.py +0 -0
  522. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_file_ignore_defaults.py +0 -0
  523. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_find_cmd.py +0 -0
  524. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_firstuser_findings.py +0 -0
  525. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_freshness_helper.py +0 -0
  526. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_gain_coverage.py +0 -0
  527. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_gain_ratio.py +0 -0
  528. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_gating_join_field_docstrings.py +0 -0
  529. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_git_delta.py +0 -0
  530. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_git_hooks.py +0 -0
  531. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_git_hooks_notify.py +0 -0
  532. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_graph_backend.py +0 -0
  533. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_graph_completeness_invariant.py +0 -0
  534. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_hard_kill_pool.py +0 -0
  535. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_has_column_precedence_upsert.py +0 -0
  536. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_hook_reindex_detach.py +0 -0
  537. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_hygiene_config_warning.py +0 -0
  538. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_identity_counters.py +0 -0
  539. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_include_working_tree.py +0 -0
  540. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_index_cmd.py +0 -0
  541. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_index_filter_config.py +0 -0
  542. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_index_flags.py +0 -0
  543. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_index_progress.py +0 -0
  544. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_index_summary_degraded_metric.py +0 -0
  545. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_indexer_progress.py +0 -0
  546. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_indexer_quality.py +0 -0
  547. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_install.py +0 -0
  548. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_install_message.py +0 -0
  549. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_issue_63_readonly_lock.py +0 -0
  550. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_jobs.py +0 -0
  551. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_join_col_resolve_marker.py +0 -0
  552. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_judgement.py +0 -0
  553. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_lineage_conversion.py +0 -0
  554. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_literal_column_skip.py +0 -0
  555. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_mcp_best_practices.py +0 -0
  556. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_mcp_control.py +0 -0
  557. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_mcp_stdio_smoke.py +0 -0
  558. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_metrics.py +0 -0
  559. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_noise_filter.py +0 -0
  560. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_normalize_keys.py +0 -0
  561. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_parse_failed_classification.py +0 -0
  562. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_parse_file_dependency_filter.py +0 -0
  563. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_parse_quality.py +0 -0
  564. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_parser.py +0 -0
  565. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_perf_scaling_guard.py +0 -0
  566. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_phantom_non_table_create_source.py +0 -0
  567. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_pr07_observability.py +0 -0
  568. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_pr6_execute_immediate_unwrap.py +0 -0
  569. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_pr_impact_unit.py +0 -0
  570. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_qualify_failed_unit.py +0 -0
  571. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_queries_loader.py +0 -0
  572. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_read_client.py +0 -0
  573. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_repo_relative_cte_namespaces.py +0 -0
  574. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_resolvable_write_col_edges_unit.py +0 -0
  575. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_resolve_join_columns_sql.py +0 -0
  576. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +0 -0
  577. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_schema_resolver.py +0 -0
  578. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_selects_from_completeness_unit.py +0 -0
  579. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_selfheal_detector.py +0 -0
  580. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_selfheal_pr1_messages.py +0 -0
  581. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_selfheal_reexec.py +0 -0
  582. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_selfheal_watcher.py +0 -0
  583. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_server.py +0 -0
  584. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_skip_counts_persistence.py +0 -0
  585. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
  586. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_sprint_06_t04_t05.py +0 -0
  587. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_star_resolution_unit.py +0 -0
  588. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_star_schema_unit.py +0 -0
  589. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_submit_feedback.py +0 -0
  590. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_subprocess_isolate.py +0 -0
  591. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_t02_expression_name_extraction.py +0 -0
  592. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_t03_ddl_skip.py +0 -0
  593. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_temp_table_namespacing.py +0 -0
  594. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_timeout_cancel.py +0 -0
  595. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_tool_version_stamp.py +0 -0
  596. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_tools_hints.py +0 -0
  597. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_tools_warnings.py +0 -0
  598. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_transform_kind_classification.py +0 -0
  599. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_uninstall.py +0 -0
  600. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_unknown_sentinel_skip.py +0 -0
  601. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_unqualified_fallback.py +0 -0
  602. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_upsert_batch_invariant.py +0 -0
  603. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_use_schema_session_context.py +0 -0
  604. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_version_parity.py +0 -0
  605. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_view_classification.py +0 -0
  606. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_viz_config_schemas.py +0 -0
  607. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_viz_facets.py +0 -0
  608. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_viz_render_self_contained.py +0 -0
  609. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_walker.py +0 -0
  610. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_watcher.py +0 -0
  611. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_worker_error_classification.py +0 -0
  612. {sql_code_graph-1.35.1 → sql_code_graph-1.35.2}/tests/unit/test_writer_queue.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-code-graph
3
- Version: 1.35.1
3
+ Version: 1.35.2
4
4
  Summary: SQL code graph analyzer and lineage tracer
5
5
  Project-URL: Homepage, https://github.com/Warhorze/sql-code-graph
6
6
  Project-URL: Repository, https://github.com/Warhorze/sql-code-graph
@@ -0,0 +1,31 @@
1
+ {"total_calls": 1616, "last_7d_calls": 1616, "index_runs": 5, "feedback_tp": 0,
2
+ "feedback_total": 0, "top_tools": [{"name": "execute_sql", "count": 544},
3
+ {"name": "trace_column_lineage", "count": 425}, {"name":
4
+ "list_dialects_and_repos", "count": 139}], "execute_sql_ratio": 0.34,
5
+ "parse_quality": {"sqlglot": 5166, "scripting": 20, "dynamic_sql": 3},
6
+ "coverage": {"catalogued_tables": 5800, "total_tables": 6552, "good_edges":
7
+ 52678, "total_edges": 60826, "phantom_edges": 12241, "blindspot_tables": 628,
8
+ "good_edges_strict": 48151, "edge_health_strict_pct": 79.16,
9
+ "good_edges_scoped": 37471, "total_edges_scoped": 38020,
10
+ "edge_health_scoped_pct": 98.56, "phantom_confirmed": 11701,
11
+ "phantom_contradicted": 352, "phantom_unverified": 188, "top_blindspot_tables":
12
+ [{"table": "ba.wtfa_kpi_datum_klant", "bad_edges": 70}, {"table":
13
+ "ba.wtfs_voorraad_dagstand", "bad_edges": 55}, {"table":
14
+ "ba.wtfs_voorraad_zondagstand", "bad_edges": 55}, {"table":
15
+ "da.rtgmd_postnl_customer_usage", "bad_edges": 43}, {"table":
16
+ "da.rtgmd_postnl_athome_3s", "bad_edges": 33}, {"table":
17
+ "wtfe_kpi_voorraad_artikel_voorraadlocatie", "bad_edges": 32}, {"table":
18
+ "da.rtgmd_postnl_facturen", "bad_edges": 30}, {"table": "da.hthyb_pages",
19
+ "bad_edges": 23}, {"table": "da.rtgmd_dhb_extra_kosten", "bad_edges": 19},
20
+ {"table": "da.hthyb_page_brandplacement", "bad_edges": 17}],
21
+ "blindspot_tables_for_80pct": 17, "files_indexed": 1335, "indexed_sha":
22
+ "fdf1b551a34601a6cf3ce1c8b9f76e27ce2753e6", "db_path": "/tmp/mergec_after.db",
23
+ "index_timestamp": 1781470021.8137639, "degraded_parse_total": 5189,
24
+ "degraded_parse_queries": 27, "degraded_parse_by_dir": {"etl": {"degraded": 8,
25
+ "total": 2776}, "ddl": {"degraded": 19, "total": 2413}},
26
+ "zero_edge_write_queries": 1028, "total_write_queries": 2323,
27
+ "cte_key_collisions": 0, "rescuable_unqualified_edges": 125,
28
+ "info_schema_has_column_rows": 100193, "cte_source_gap_writes": 0,
29
+ "resolvable_write_col_edges": 36936, "transitive_col_edges": 4178,
30
+ "qualify_failed_statements": 9, "tool_version_stale": false,
31
+ "indexed_tool_version": "1.35.2", "running_tool_version": "1.35.2"}}
@@ -0,0 +1,31 @@
1
+ {"total_calls": 1616, "last_7d_calls": 1616, "index_runs": 5, "feedback_tp": 0,
2
+ "feedback_total": 0, "top_tools": [{"name": "execute_sql", "count": 544},
3
+ {"name": "trace_column_lineage", "count": 425}, {"name":
4
+ "list_dialects_and_repos", "count": 139}], "execute_sql_ratio": 0.34,
5
+ "parse_quality": {"sqlglot": 5166, "scripting": 20, "dynamic_sql": 3},
6
+ "coverage": {"catalogued_tables": 5800, "total_tables": 6552, "good_edges":
7
+ 52671, "total_edges": 60819, "phantom_edges": 12241, "blindspot_tables": 628,
8
+ "good_edges_strict": 48140, "edge_health_strict_pct": 79.15,
9
+ "good_edges_scoped": 37460, "total_edges_scoped": 38009,
10
+ "edge_health_scoped_pct": 98.56, "phantom_confirmed": 11701,
11
+ "phantom_contradicted": 352, "phantom_unverified": 188, "top_blindspot_tables":
12
+ [{"table": "ba.wtfa_kpi_datum_klant", "bad_edges": 70}, {"table":
13
+ "ba.wtfs_voorraad_dagstand", "bad_edges": 55}, {"table":
14
+ "ba.wtfs_voorraad_zondagstand", "bad_edges": 55}, {"table":
15
+ "da.rtgmd_postnl_customer_usage", "bad_edges": 43}, {"table":
16
+ "da.rtgmd_postnl_athome_3s", "bad_edges": 33}, {"table":
17
+ "wtfe_kpi_voorraad_artikel_voorraadlocatie", "bad_edges": 32}, {"table":
18
+ "da.rtgmd_postnl_facturen", "bad_edges": 30}, {"table": "da.hthyb_pages",
19
+ "bad_edges": 23}, {"table": "da.rtgmd_dhb_extra_kosten", "bad_edges": 19},
20
+ {"table": "da.hthyb_page_brandplacement", "bad_edges": 17}],
21
+ "blindspot_tables_for_80pct": 17, "files_indexed": 1335, "indexed_sha":
22
+ "fdf1b551a34601a6cf3ce1c8b9f76e27ce2753e6", "db_path": "/tmp/mergec_before.db",
23
+ "index_timestamp": 1781469837.2725205, "degraded_parse_total": 5189,
24
+ "degraded_parse_queries": 20, "degraded_parse_by_dir": {"etl": {"degraded": 1,
25
+ "total": 2776}, "ddl": {"degraded": 19, "total": 2413}},
26
+ "zero_edge_write_queries": 1034, "total_write_queries": 2323,
27
+ "cte_key_collisions": 0, "rescuable_unqualified_edges": 125,
28
+ "info_schema_has_column_rows": 100193, "cte_source_gap_writes": 0,
29
+ "resolvable_write_col_edges": 36936, "transitive_col_edges": 4182,
30
+ "qualify_failed_statements": 9, "tool_version_stale": false,
31
+ "indexed_tool_version": "1.35.1", "running_tool_version": "1.35.1"}}
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sql-code-graph"
7
- version = "1.35.1"
7
+ version = "1.35.2"
8
8
  description = "SQL code graph analyzer and lineage tracer"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,5 +1,5 @@
1
1
  """SQL Code Graph - SQL lineage and dependency analysis tool."""
2
2
 
3
- __version__ = "1.35.1"
3
+ __version__ = "1.35.2"
4
4
 
5
5
  __all__ = ["__version__"]
@@ -637,12 +637,14 @@ class SqlParser(ABC):
637
637
  """Return True if `_extract_column_lineage` would attempt extraction for `stmt`.
638
638
 
639
639
  Mirrors the type/body checks `_extract_column_lineage` (below, this class)
640
- already performs: only `exp.Select`, `exp.Insert` with a `SELECT` body, and
641
- `exp.Create` with a `Select`/`Subquery` body (CTAS / CREATE VIEW AS SELECT)
642
- can ever produce column-lineage edges. `exp.Merge` is explicitly skipped there
643
- (T-07-06, deferred). Everything else (Update, Delete, Use, Set, Comment, Drop,
644
- Alter, Command, TruncateTable, CREATE ... LIKE/CLONE/column-defs, INSERT ...
645
- VALUES) is structurally lineage-free regardless of `build_scope`'s outcome.
640
+ already performs: only `exp.Select`, `exp.Insert` with a `SELECT` body,
641
+ `exp.Create` with a `Select`/`Subquery` body (CTAS / CREATE VIEW AS SELECT),
642
+ and `exp.Merge` (column edges extracted structurally from its WHEN clauses —
643
+ see `_extract_merge_lineage`, plan/sprints/sprint_snowflake_lineage_patterns.md
644
+ PR-C) can ever produce column-lineage edges. Everything else (Update, Delete,
645
+ Use, Set, Comment, Drop, Alter, Command, TruncateTable, CREATE ...
646
+ LIKE/CLONE/column-defs, INSERT ... VALUES) is structurally lineage-free
647
+ regardless of `build_scope`'s outcome.
646
648
 
647
649
  Used by `AnsiParser._parse_statement` to avoid marking `parse_failed=True`
648
650
  for statement kinds that were never going to produce column lineage in the
@@ -658,8 +660,185 @@ class SqlParser(ABC):
658
660
  return isinstance(stmt.expression, exp.Select)
659
661
  if isinstance(stmt, exp.Create):
660
662
  return isinstance(stmt.expression, (exp.Select, exp.Subquery))
663
+ if isinstance(stmt, exp.Merge):
664
+ return True
661
665
  return False
662
666
 
667
+ def _extract_merge_lineage(
668
+ self,
669
+ stmt: Any,
670
+ dst_table: "TableRef | None",
671
+ query_sources: list["TableRef"] | None,
672
+ out: ParsedFile,
673
+ ) -> list[LineageEdge]:
674
+ """Extract column-level lineage from a MERGE statement's WHEN clauses.
675
+
676
+ MERGE column edges cannot come from sqlglot's ``lineage()`` (it does not model
677
+ MERGE branches), but the ``WHEN MATCHED ... UPDATE SET`` and
678
+ ``WHEN NOT MATCHED ... INSERT (cols) VALUES (vals)`` clauses are structurally
679
+ extractable by a direct AST walk. This method performs that walk: it is bounded
680
+ and runs ONCE PER MERGE statement — it NEVER calls ``sg_lineage``, ``qualify``,
681
+ ``build_scope`` or ``exp.expand`` (AC-C7,
682
+ plan/sprints/sprint_snowflake_lineage_patterns.md PR-C).
683
+
684
+ Resolution model:
685
+ - The MERGE target (``stmt.this``) and source (``stmt.args['using']``) are both
686
+ captured in ``query_sources`` as already-qualified TableRefs (the table-grain
687
+ path does NOT split them into target/sources for MERGE — ``dst_table`` is
688
+ ``None`` here, so AC-C3's shipped table-grain behaviour is preserved). This
689
+ method matches ``stmt.this``/``using`` back to those refs by alias+name to
690
+ identify which is the target and which the source(s), then builds an
691
+ alias -> TableRef map over both.
692
+ - MATCHED UPDATE: each ``exp.EQ`` is ``target_col = source_expr``; the dst is a
693
+ column on the target, the src columns are every ``exp.Column`` in the RHS
694
+ (multi-source expressions emit one edge per source column — AC-C4). A
695
+ pure-literal RHS (no ``exp.Column``) contributes no edge (AC-C5) — mirrors the
696
+ pure-literal skip invariant.
697
+ - NOT MATCHED INSERT: ``then.this`` is the target column tuple, ``then.expression``
698
+ the values tuple; zip positionally and emit per source column. An INSERT with
699
+ no column list (``then.this is None``) is skip-and-logged
700
+ (``col_lineage_skip:merge_no_collist:``) — NO positional DDL fallback (gate
701
+ decision: positional guessing risks wrong edges).
702
+
703
+ Args:
704
+ stmt: the ``exp.Merge`` AST node.
705
+ dst_table: the resolved INSERT/CREATE target TableRef from the caller. For
706
+ MERGE this is ``None`` (the table-grain path leaves the target in
707
+ ``query_sources``); the target is recovered here from ``stmt.this``.
708
+ query_sources: resolved table refs for the MERGE (target + ``USING``
709
+ source(s)), each carrying its ``.alias``, fully qualified.
710
+ out: ParsedFile, for skip/unresolved error records.
711
+
712
+ Returns:
713
+ List of LineageEdge (may be empty).
714
+ """
715
+ import sqlglot.expressions as exp
716
+
717
+ edges: list[LineageEdge] = []
718
+ refs = list(query_sources or [])
719
+ if dst_table is not None:
720
+ refs.append(dst_table)
721
+
722
+ # Identify the MERGE target ref by matching stmt.this against the resolved refs.
723
+ # `_real_tables` does not preserve the AST alias on the TableRef, so match on the
724
+ # AST target's name (and alias, as a fallback) against each ref's name/alias.
725
+ # The remaining refs are the USING source(s).
726
+ target_ast = stmt.this if isinstance(stmt.this, exp.Table) else None
727
+ target_keys: set[str] = set()
728
+ if target_ast is not None:
729
+ if target_ast.name:
730
+ target_keys.add(target_ast.name.lower())
731
+ if target_ast.alias:
732
+ target_keys.add(target_ast.alias.lower())
733
+
734
+ def _ref_keys(ref: TableRef) -> set[str]:
735
+ keys: set[str] = set()
736
+ if ref.alias:
737
+ keys.add(ref.alias.lower())
738
+ if ref.name:
739
+ keys.add(ref.name.lower())
740
+ return keys
741
+
742
+ target_ref: TableRef | None = None
743
+ if target_keys:
744
+ for ref in refs:
745
+ if target_keys & _ref_keys(ref):
746
+ target_ref = ref
747
+ break
748
+ if target_ref is None:
749
+ label = ".".join(sorted(target_keys)) or "<unknown>"
750
+ out.errors.append(f"col_lineage_skip:merge_no_target:{label}")
751
+ return edges
752
+
753
+ source_refs = [r for r in refs if r is not target_ref]
754
+
755
+ # Build an alias/name -> TableRef map over the target + USING source(s).
756
+ # MERGE column references qualify by the table alias (e.g. `target.name`,
757
+ # `s.name`). `_real_tables` strips the alias from the resolved TableRef, so the
758
+ # alias is recovered from the AST nodes (target=stmt.this, source=using) and
759
+ # mapped to its resolved ref. Bare table names are registered as a fallback.
760
+ alias_map: dict[str, TableRef] = {}
761
+
762
+ def _register(ref: TableRef | None, ast_node: Any) -> None:
763
+ if ref is None:
764
+ return
765
+ if isinstance(ast_node, exp.Table) and ast_node.alias:
766
+ alias_map.setdefault(ast_node.alias.lower(), ref)
767
+ if ref.alias:
768
+ alias_map.setdefault(ref.alias.lower(), ref)
769
+ if ref.name:
770
+ alias_map.setdefault(ref.name.lower(), ref)
771
+
772
+ using_ast = stmt.args.get("using")
773
+ _register(target_ref, target_ast)
774
+ for src in source_refs:
775
+ _register(src, using_ast if len(source_refs) == 1 else None)
776
+
777
+ def _resolve_table(col: Any) -> TableRef | None:
778
+ """Resolve the owning TableRef of a source column reference."""
779
+ tbl_name = col.table
780
+ if tbl_name:
781
+ return alias_map.get(tbl_name.lower())
782
+ # Unqualified RHS column — attribute to the lone source when unambiguous.
783
+ if len(source_refs) == 1:
784
+ return source_refs[0]
785
+ return None
786
+
787
+ def _emit(target_col_name: str, rhs: Any, transform: str) -> None:
788
+ """Emit one edge per source ``exp.Column`` found in ``rhs``."""
789
+ if not target_col_name:
790
+ return
791
+ cols = list(rhs.find_all(exp.Column)) if rhs is not None else []
792
+ if not cols:
793
+ # Pure-literal / no source column — no edge (AC-C5).
794
+ return
795
+ dst_ref = ColumnRef(table=target_ref, name=target_col_name)
796
+ for col in cols:
797
+ src_table = _resolve_table(col)
798
+ if src_table is None:
799
+ out.errors.append(
800
+ f"col_lineage_skip:merge_unresolved:{col.table or ''}.{col.name}"
801
+ )
802
+ continue
803
+ edges.append(
804
+ LineageEdge(
805
+ src=ColumnRef(table=src_table, name=col.name),
806
+ dst=dst_ref,
807
+ transform=transform,
808
+ )
809
+ )
810
+
811
+ for when in stmt.find_all(exp.When):
812
+ then = when.args.get("then")
813
+ if isinstance(then, exp.Update):
814
+ # WHEN MATCHED THEN UPDATE SET target.a = s.a, target.b = s.x + s.y
815
+ for eq in then.expressions:
816
+ if not isinstance(eq, exp.EQ):
817
+ continue
818
+ lhs = eq.this
819
+ if not isinstance(lhs, exp.Column):
820
+ continue
821
+ _emit(lhs.name, eq.expression, "MERGE_UPDATE")
822
+ elif isinstance(then, exp.Insert):
823
+ # WHEN NOT MATCHED THEN INSERT (cols) VALUES (vals)
824
+ target_cols = then.this
825
+ values = then.expression
826
+ if target_cols is None:
827
+ # INSERT VALUES with no column list — skip-and-log, no positional
828
+ # DDL fallback (gate decision: positional guessing risks wrong edges).
829
+ out.errors.append(f"col_lineage_skip:merge_no_collist:{target_ref.full_id}")
830
+ continue
831
+ col_exprs = list(getattr(target_cols, "expressions", []) or [])
832
+ val_exprs = list(getattr(values, "expressions", []) or [])
833
+ # Positional alignment of (cols) with VALUES (...); a malformed MERGE
834
+ # with mismatched arities zips to the shorter list rather than raising.
835
+ for target_col, value in zip(col_exprs, val_exprs, strict=False):
836
+ if not isinstance(target_col, exp.Column):
837
+ continue
838
+ _emit(target_col.name, value, "MERGE_INSERT")
839
+
840
+ return edges
841
+
663
842
  def _real_tables(self, scope: Any) -> list[TableRef]:
664
843
  """Return real (non-CTE) tables referenced in a scope.
665
844
 
@@ -1117,19 +1296,15 @@ class SqlParser(ABC):
1117
1296
  join_col_resolves: list[JoinColResolve] = []
1118
1297
  _qualify_failed: bool = False
1119
1298
 
1120
- # NEW (T-07-06): Record MERGE statements explicitly as deferred.
1121
- # sqlglot's lineage() API does not handle MERGE branches; implementing
1122
- # multi-branch lineage is deferred (see plan/sprints/sprint_07_open_ecodes.md § T-07-06).
1123
- # TODO: Remove when sqlglot adds MERGE lineage support (T-07-06).
1299
+ # MERGE column lineage (un-defer T-07-06,
1300
+ # plan/sprints/sprint_snowflake_lineage_patterns.md PR-C). sqlglot's lineage()
1301
+ # API does not handle MERGE branches, but the WHEN MATCHED UPDATE SET / WHEN NOT
1302
+ # MATCHED INSERT VALUES clauses are structurally extractable by a direct AST walk.
1303
+ # This is a bounded once-per-statement path that NEVER calls sg_lineage / qualify /
1304
+ # build_scope / exp.expand (AC-C7).
1124
1305
  if isinstance(stmt, exp.Merge):
1125
- dst_name = None
1126
- if stmt.this is not None:
1127
- try:
1128
- dst_name = stmt.this.name
1129
- except Exception:
1130
- dst_name = None
1131
- out.errors.append(f"col_lineage_skip:merge_branch:{dst_name or '<unknown>'}")
1132
- return LineageExtraction(edges=edges, star_sources=star_sources)
1306
+ merge_edges = self._extract_merge_lineage(stmt, dst_table, query_sources, out)
1307
+ return LineageExtraction(edges=merge_edges, star_sources=star_sources)
1133
1308
 
1134
1309
  # Only extract column lineage for certain statement types
1135
1310
  if not isinstance(stmt, (exp.Select, exp.Insert, exp.Create)):
@@ -0,0 +1,170 @@
1
+ """Dialect-agnostic bounded constant-fold of dynamic table-name expressions.
2
+
3
+ This is the pure core of the "generic variable-name resolution" feature
4
+ (``plan/sprints/feature_generic_var_name_resolution.md``). It partially folds a
5
+ string-valued expression AST (string literals, ``||`` / ``CONCAT``, and 1-hop
6
+ ``$var`` references) into a concrete ``[catalog.]db.name`` table reference,
7
+ recovering the statically-determined trailing identifier components while
8
+ honestly giving up when the name cannot be determined.
9
+
10
+ No parser/indexer state is touched here: ``resolve_dynamic_name`` is a pure
11
+ function, fully unit-testable in isolation. PR-2 wires it into the Snowflake
12
+ parser via a sink predicate; this module ships unwired.
13
+
14
+ Fold classification:
15
+
16
+ * **LIT (resolvable):** ``exp.Literal`` (string), ``exp.DPipe`` / ``exp.Concat``
17
+ over folds, and a 1-hop ``$var`` whose RHS (looked up in ``var_env`` exactly
18
+ once) itself folds to a leading constant prefix.
19
+ * **OPAQUE (unresolvable):** runtime functions (``current_database()``,
20
+ ``split_part(...)``, ``current_warehouse()``, any ``exp.Func`` /
21
+ ``exp.Anonymous`` that is not a pure string op), scalar subqueries that are not
22
+ a single-projection of folds, bind parameters (``exp.Placeholder``), and any
23
+ ``$var`` reference at chain depth >= 2.
24
+
25
+ Name extraction interprets the fold as ``[catalog.]db.name`` (name-last,
26
+ dot-split): it keeps the rightmost statically-determined ``db.name`` tail,
27
+ wildcards (drops) a leading OPAQUE catalog, keeps a static *literal* catalog, and
28
+ returns ``None`` when the whole thing is opaque / the tail is a bare name / the
29
+ tail lacks a resolvable ``db.name``.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from dataclasses import dataclass
35
+
36
+ import sqlglot.expressions as exp
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class _Lit:
41
+ """A statically-known string segment of the folded expression."""
42
+
43
+ text: str
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class _Opaque:
48
+ """A runtime-determined segment that cannot be folded statically."""
49
+
50
+
51
+ _Part = _Lit | _Opaque
52
+
53
+
54
+ def _fold_parts(
55
+ node: exp.Expression, # type: ignore[attr-defined]
56
+ var_env: dict[str, exp.Expression], # type: ignore[attr-defined]
57
+ *,
58
+ chain_depth: int,
59
+ ) -> list[_Part]:
60
+ """Fold ``node`` into an ordered list of LIT / OPAQUE parts.
61
+
62
+ Descends string-concatenation structure (``||`` / ``CONCAT``), single-
63
+ projection subqueries and parentheses; resolves 1-hop ``$var`` references
64
+ against ``var_env``; classifies everything else OPAQUE.
65
+ """
66
+ # Unwrap a single-projection (SELECT ...) scalar subquery / paren.
67
+ if isinstance(node, exp.Subquery):
68
+ return _fold_parts(node.this, var_env, chain_depth=chain_depth)
69
+ if isinstance(node, exp.Paren):
70
+ return _fold_parts(node.this, var_env, chain_depth=chain_depth)
71
+ if isinstance(node, exp.Select):
72
+ projections = node.expressions
73
+ if len(projections) != 1:
74
+ return [_Opaque()]
75
+ return _fold_parts(projections[0], var_env, chain_depth=chain_depth)
76
+
77
+ # String concatenation: DPipe is binary (left-nested), Concat is n-ary.
78
+ if isinstance(node, exp.DPipe):
79
+ return _fold_parts(node.this, var_env, chain_depth=chain_depth) + _fold_parts(
80
+ node.expression, var_env, chain_depth=chain_depth
81
+ )
82
+ if isinstance(node, exp.Concat):
83
+ parts: list[_Part] = []
84
+ for child in node.expressions:
85
+ parts.extend(_fold_parts(child, var_env, chain_depth=chain_depth))
86
+ return parts
87
+
88
+ # Concrete string literal.
89
+ if isinstance(node, exp.Literal) and node.is_string:
90
+ return [_Lit(node.this)]
91
+
92
+ # 1-hop $var reference.
93
+ if isinstance(node, exp.Parameter):
94
+ var = node.this
95
+ name = var.name if isinstance(var, exp.Var) else None
96
+ if name is None or chain_depth < 1:
97
+ return [_Opaque()]
98
+ rhs = var_env.get(name.lower())
99
+ if rhs is None:
100
+ return [_Opaque()]
101
+ # Resolve exactly one hop: the looked-up RHS may not itself follow
102
+ # further $vars (depth-2 is OPAQUE because chain_depth drops to 0).
103
+ return _fold_parts(rhs, var_env, chain_depth=chain_depth - 1)
104
+
105
+ # Everything else (runtime funcs, bind params, non-fold subqueries) is opaque.
106
+ return [_Opaque()]
107
+
108
+
109
+ def resolve_dynamic_name(
110
+ rhs_expr: exp.Expression, # type: ignore[attr-defined]
111
+ var_env: dict[str, exp.Expression], # type: ignore[attr-defined]
112
+ *,
113
+ chain_depth: int = 1,
114
+ ) -> exp.Table | None:
115
+ """Bounded partial constant-fold of a string-expression AST into a TableRef.
116
+
117
+ Args:
118
+ rhs_expr: the RHS expression assigned to the dynamic name (the AST that
119
+ the ``IDENTIFIER($var)`` sink dereferences).
120
+ var_env: lowercased var name -> its RHS AST, for 1-hop chain resolution.
121
+ chain_depth: max var-lookup hops (default 1; corpus max is 1). A var
122
+ whose value references another var resolves only the first hop.
123
+
124
+ Returns:
125
+ An ``exp.Table`` for the resolvable trailing identifier components, or
126
+ ``None`` to give up honestly (caller leaves the sink dropped).
127
+ """
128
+ parts = _fold_parts(rhs_expr, var_env, chain_depth=chain_depth)
129
+
130
+ if not parts:
131
+ return None
132
+
133
+ # Take the rightmost contiguous run of LIT parts (the static suffix), noting
134
+ # whether an OPAQUE segment sits immediately before that run (catalog
135
+ # position is then runtime-determined).
136
+ suffix_lits: list[str] = []
137
+ opaque_precedes_suffix = False
138
+ for part in reversed(parts):
139
+ if isinstance(part, _Lit):
140
+ suffix_lits.append(part.text)
141
+ else:
142
+ opaque_precedes_suffix = True
143
+ break
144
+ suffix_lits.reverse()
145
+
146
+ if not suffix_lits:
147
+ # All-opaque (no static tail at all).
148
+ return None
149
+
150
+ suffix = "".join(suffix_lits)
151
+ table = exp.to_table(suffix, dialect="snowflake")
152
+
153
+ # A resolvable object id needs at least db.name (schema.table). A bare name
154
+ # (no db) is a give-up: we never guess the schema/table. A missing name (tail
155
+ # ends on a dot) is likewise unresolvable.
156
+ if table.db == "" or table.name == "":
157
+ return None
158
+
159
+ # Catalog policy:
160
+ # - literal catalog present in the static suffix (3-part name) -> KEEP it.
161
+ # - an OPAQUE segment precedes the suffix (the catalog slot came from a
162
+ # runtime segment) -> wildcard / drop the catalog (emit catalog-less
163
+ # db.name) so the node merges with DDL / plain-SQL refs to the same table.
164
+ # to_table already yields catalog='' when the static suffix had no catalog
165
+ # component (e.g. '.EMP.APPLICATION_FIELDS' or 'DHB.KOSTEN'); the explicit
166
+ # drop only matters when an opaque prefix sits before a literal 3-part tail.
167
+ if opaque_precedes_suffix and table.catalog != "":
168
+ table.set("catalog", None)
169
+
170
+ return table
@@ -181,15 +181,17 @@ def test_skip_counts_queryable_across_corpus(db, tmp_path):
181
181
  def test_skip_counts_index_full_file_populates_column(db, tmp_path):
182
182
  """Indexing a real SQL file through the full index_repo path persists skip_counts.
183
183
 
184
- Uses a Snowflake SQL fixture with a MERGE statement (guaranteed to emit
185
- col_lineage_skip:merge_branch:*) to verify the end-to-end path from parse
186
- normalize_keys _build_file_rows upsert_nodes_bulk → File.skip_counts.
184
+ Uses a Snowflake SQL fixture with a MERGE whose NOT MATCHED INSERT omits a column
185
+ list (guaranteed to emit col_lineage_skip:merge_no_collist:* see
186
+ plan/sprints/sprint_snowflake_lineage_patterns.md PR-C) to verify the end-to-end
187
+ path from parse → normalize_keys → _build_file_rows → upsert_nodes_bulk →
188
+ File.skip_counts.
187
189
  """
188
- # MERGE statements emit col_lineage_skip:merge_branch:*
190
+ # A no-column-list MERGE INSERT emits col_lineage_skip:merge_no_collist:*
189
191
  sql = (
190
192
  "CREATE TABLE src (a INT, b INT);\n"
191
193
  "MERGE INTO tgt USING src ON tgt.a = src.a\n"
192
- "WHEN MATCHED THEN UPDATE SET tgt.b = src.b;\n"
194
+ "WHEN NOT MATCHED THEN INSERT VALUES (src.a, src.b);\n"
193
195
  )
194
196
  sql_file = tmp_path / "merge_fixture.sf.sql"
195
197
  sql_file.write_text(sql)
@@ -201,15 +203,15 @@ def test_skip_counts_index_full_file_populates_column(db, tmp_path):
201
203
  {"path": str(sql_file)},
202
204
  )
203
205
  assert len(rows) == 1, f"File row not found for {sql_file}"
204
- # MERGE emits at least one merge_branch skip
206
+ # The no-collist MERGE INSERT emits at least one merge_no_collist skip
205
207
  raw = rows[0]["skip_counts"]
206
208
  assert raw is not None, (
207
- "skip_counts must be non-null for a file containing a MERGE statement "
208
- f"(expected col_lineage_skip:merge_branch:*). Got NULL. File: {sql_file}"
209
+ "skip_counts must be non-null for a file containing a no-collist MERGE INSERT "
210
+ f"(expected col_lineage_skip:merge_no_collist:*). Got NULL. File: {sql_file}"
209
211
  )
210
212
  counts = json.loads(raw)
211
- assert counts.get("merge_branch", 0) >= 1, (
212
- f"Expected merge_branch >= 1 in skip_counts. Got {counts!r}"
213
+ assert counts.get("merge_no_collist", 0) >= 1, (
214
+ f"Expected merge_no_collist >= 1 in skip_counts. Got {counts!r}"
213
215
  )
214
216
 
215
217
 
@@ -0,0 +1,59 @@
1
+ """E16: MERGE multi-branch column lineage (structural extraction).
2
+
3
+ MERGE statements now produce column lineage via a direct AST walk of their
4
+ ``WHEN MATCHED ... UPDATE SET`` / ``WHEN NOT MATCHED ... INSERT (cols) VALUES (...)``
5
+ clauses — sqlglot's ``lineage()`` API does not visit MERGE branches, so this is a
6
+ dedicated structural path (no ``sg_lineage`` / ``qualify``).
7
+
8
+ Un-defers the E16/T-07-06 deferral. See
9
+ plan/sprints/sprint_snowflake_lineage_patterns.md PR-C
10
+ ([plan doc](../../../plan/sprints/sprint_snowflake_lineage_patterns.md)) and the
11
+ E{n} taxonomy (plan/sprints/sprint_07_open_ecodes.md § T-07-06) for history.
12
+ """
13
+
14
+ from pathlib import Path
15
+
16
+ from tests.snowflake.conftest import edges, parse
17
+
18
+
19
+ def test_e16_merge_match_and_insert(parser):
20
+ """MATCHED UPDATE and NOT MATCHED INSERT each emit a column edge.
21
+
22
+ `UPDATE SET col = src.col_a` -> `src.col_a -> dst.col` (MERGE_UPDATE);
23
+ `INSERT (col) VALUES (src.col_b)` -> `src.col_b -> dst.col` (MERGE_INSERT).
24
+ """
25
+ sql = Path(__file__).with_name("e16_merge.sql").read_text()
26
+ result = parse(parser, sql, "e16_merge.sql")
27
+
28
+ all_edges = set(edges(result))
29
+ assert ("src", "col_a", "dst", "col") in all_edges, (
30
+ f"E16: MATCHED UPDATE edge missing; got {all_edges}"
31
+ )
32
+ assert ("src", "col_b", "dst", "col") in all_edges, (
33
+ f"E16: NOT MATCHED INSERT edge missing; got {all_edges}"
34
+ )
35
+
36
+ # No deferred-skip noise should remain for an extractable MERGE.
37
+ assert not any("col_lineage_skip:merge_branch" in e for e in result.errors), (
38
+ f"MERGE no longer defers; got errors: {result.errors}"
39
+ )
40
+
41
+
42
+ def test_e16_merge_delete(parser):
43
+ """A DELETE branch yields no edge; the UPDATE/INSERT branches still do.
44
+
45
+ `WHEN MATCHED ... THEN DELETE` has no column assignment, so it contributes no
46
+ edge, while the MATCHED UPDATE and NOT MATCHED INSERT branches still resolve.
47
+ """
48
+ sql = Path(__file__).with_name("e16_merge_delete.sql").read_text()
49
+ result = parse(parser, sql, "e16_merge_delete.sql")
50
+
51
+ all_edges = set(edges(result))
52
+ assert ("src", "col_a", "dst", "col") in all_edges, (
53
+ f"E16: MATCHED UPDATE edge missing alongside DELETE branch; got {all_edges}"
54
+ )
55
+ assert ("src", "col_b", "dst", "col") in all_edges, (
56
+ f"E16: NOT MATCHED INSERT edge missing alongside DELETE branch; got {all_edges}"
57
+ )
58
+ # The DELETE branch assigns no column, so it must not add a phantom edge.
59
+ assert len(all_edges) == 2, f"E16: DELETE branch should add no edge; got {all_edges}"
@@ -60,14 +60,14 @@ def test_plan_review_e3_ddl_quality_allows_scripting_fallback():
60
60
 
61
61
 
62
62
  # ---------------------------------------------------------------------------
63
- # BLOCKER-2 (E16): MERGE produces zero column lineage not "at least one edge"
63
+ # BLOCKER-2 (E16): MERGE now produces column lineage (T-07-06 un-deferred)
64
64
  # ---------------------------------------------------------------------------
65
- def test_plan_review_e16_merge_produces_zero_edges():
66
- """E16 MERGE must produce zero high-confidence edges (current state).
65
+ def test_plan_review_e16_merge_captures_both_branches():
66
+ """E16 MERGE captures both the MATCHED UPDATE and NOT MATCHED INSERT branches.
67
67
 
68
- The original plan asserted 'at least one edge exists', which is wrong
69
- MERGE statements produce no column_lineage. This test gates the corrected
70
- zero-edge assertion with INVERSION TARGET.
68
+ This is the inversion of the earlier zero-edge gate: MERGE column lineage is
69
+ now extracted structurally (plan/sprints/sprint_snowflake_lineage_patterns.md
70
+ PR-C), so both branches resolve src col_a / col_b -> dst.col.
71
71
  """
72
72
  p = _parser()
73
73
  sql = (
@@ -77,12 +77,9 @@ def test_plan_review_e16_merge_produces_zero_edges():
77
77
  )
78
78
  result = p.parse_file(Path("test_e16.sql"), sql)
79
79
 
80
- # INVERSION TARGET: when E16 fixed, assert edges with dst_table=="DST"
81
- # and srcs == {"COL_A", "COL_B"} (both branches captured).
82
- assert _edges(result) == [], (
83
- "E16: MERGE currently produces no column lineage; "
84
- "if this fails, E16 was partially fixed and the test must be updated"
85
- )
80
+ edges = set(_edges(result))
81
+ assert ("src", "col_a", "dst", "col") in edges, edges
82
+ assert ("src", "col_b", "dst", "col") in edges, edges
86
83
 
87
84
 
88
85
  # ---------------------------------------------------------------------------