sql-code-graph 1.2.2__tar.gz → 1.4.0__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 (440) hide show
  1. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/ARCHITECTURE_REVIEW.md +275 -2
  2. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/PKG-INFO +2 -4
  3. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/docs/cli.md +17 -12
  4. sql_code_graph-1.4.0/plan/feature_kuzu_to_duckdb_migration.md +541 -0
  5. sql_code_graph-1.4.0/plan/fix_issue29_live_test_followups.md +442 -0
  6. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_08_changelogs_fullindex.json +14 -14
  7. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_08_fullcorpus_index.json +15 -15
  8. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/pyproject.toml +2 -3
  9. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/__init__.py +1 -1
  10. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/analyze.py +138 -127
  11. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/db.py +49 -51
  12. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/find.py +5 -9
  13. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/gain.py +14 -16
  14. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/git.py +11 -4
  15. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/index.py +173 -21
  16. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/mcp.py +70 -3
  17. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/reindex.py +147 -77
  18. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/uninstall.py +9 -20
  19. sql_code_graph-1.4.0/src/sqlcg/core/__init__.py +6 -0
  20. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/config.py +25 -81
  21. sql_code_graph-1.4.0/src/sqlcg/core/duckdb_backend.py +764 -0
  22. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/freshness.py +1 -1
  23. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/graph_db.py +20 -4
  24. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/queries.py +26 -7
  25. sql_code_graph-1.4.0/src/sqlcg/core/queries.sql +249 -0
  26. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/schema.py +1 -1
  27. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/indexer.py +27 -36
  28. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/metrics/store.py +49 -1
  29. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/control.py +1 -1
  30. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/noise_filter.py +1 -1
  31. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/read_client.py +2 -2
  32. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/server.py +184 -86
  33. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/skill.py +2 -2
  34. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/tools.py +119 -41
  35. sql_code_graph-1.4.0/src/sqlcg/server/writer.py +459 -0
  36. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/bench_indexer.py +3 -3
  37. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_F2_skill_install_e2e.py +1 -1
  38. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_airbnb_e2e.py +20 -21
  39. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_golden_lineage.py +23 -27
  40. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_mcp_lifecycle.py +29 -9
  41. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_mcp_tools.py +32 -37
  42. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_star_resolution_e2e.py +10 -10
  43. sql_code_graph-1.4.0/tests/fixtures/duckdb_parity/kuzu_reference.json +146 -0
  44. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/snowflake/test_insert_select.py +8 -7
  45. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_T34_presentation_segregation.py +3 -3
  46. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_T35_external_consumers.py +19 -20
  47. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_anchor_tools.py +3 -3
  48. sql_code_graph-1.4.0/tests/integration/test_bulk_upsert.py +150 -0
  49. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_column_lineage_e2e.py +3 -3
  50. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cross_file_lineage.py +9 -9
  51. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_recall_guard.py +22 -22
  52. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_schema_alias_guard.py +21 -28
  53. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_source_node_invariant.py +11 -11
  54. sql_code_graph-1.4.0/tests/integration/test_dialect_auto_resolution.py +178 -0
  55. sql_code_graph-1.4.0/tests/integration/test_duckdb_parity.py +246 -0
  56. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_e36_xfile_regression_guard.py +8 -8
  57. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_freshness_mcp.py +9 -46
  58. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_hygiene_config_root_reconciliation.py +3 -3
  59. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_batching.py +26 -29
  60. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_commits.py +3 -20
  61. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_to_graph.py +15 -8
  62. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_live_anchors.py +19 -16
  63. sql_code_graph-1.4.0/tests/integration/test_mvcc_rebuild.py +220 -0
  64. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_parse_diagnostics.py +8 -8
  65. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr1_confidence_reason.py +3 -3
  66. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr2_source_location.py +14 -14
  67. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr3_kind_tagging.py +8 -6
  68. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_read_via_server.py +35 -28
  69. sql_code_graph-1.4.0/tests/integration/test_readonly_under_lock.py +281 -0
  70. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_reindex_via_server.py +72 -39
  71. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_resync.py +17 -16
  72. sql_code_graph-1.4.0/tests/integration/test_single_writer_queue.py +394 -0
  73. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_star_resolution.py +37 -33
  74. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_union_cte_star_recall_guard.py +17 -25
  75. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_user_surface_recall_guard.py +17 -38
  76. sql_code_graph-1.4.0/tests/unit/test_BugB_escalation_uses_init_path.py +86 -0
  77. sql_code_graph-1.4.0/tests/unit/test_BugC_hook_upgrade.py +184 -0
  78. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_install_skill.py +1 -1
  79. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_aggregator.py +2 -2
  80. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_aggregator_skip.py +2 -2
  81. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_closure_depth.py +8 -8
  82. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_db_info.py +27 -17
  83. sql_code_graph-1.4.0/tests/unit/test_duckdb_backend.py +423 -0
  84. sql_code_graph-1.2.2/tests/unit/test_kuzu_backend.py → sql_code_graph-1.4.0/tests/unit/test_duckdb_backend_shared.py +50 -34
  85. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_hooks_notify.py +29 -0
  86. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_hygiene_config_warning.py +0 -1
  87. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_include_working_tree.py +0 -1
  88. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_cmd.py +0 -2
  89. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_flags.py +0 -3
  90. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_progress.py +3 -3
  91. sql_code_graph-1.4.0/tests/unit/test_mcp_stdio_smoke.py +76 -0
  92. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_pr07_observability.py +6 -6
  93. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_queries_loader.py +23 -25
  94. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_read_client.py +1 -1
  95. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +2 -2
  96. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_star_schema_unit.py +17 -15
  97. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_uninstall.py +42 -45
  98. sql_code_graph-1.4.0/tests/unit/test_writer_queue.py +207 -0
  99. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/uv.lock +33 -44
  100. sql_code_graph-1.2.2/src/sqlcg/core/__init__.py +0 -8
  101. sql_code_graph-1.2.2/src/sqlcg/core/kuzu_backend.py +0 -445
  102. sql_code_graph-1.2.2/src/sqlcg/core/neo4j_backend.py +0 -233
  103. sql_code_graph-1.2.2/tests/integration/test_bulk_upsert.py +0 -255
  104. sql_code_graph-1.2.2/tests/integration/test_readonly_under_lock.py +0 -419
  105. sql_code_graph-1.2.2/tests/unit/test_kuzu_lock.py +0 -91
  106. sql_code_graph-1.2.2/tests/unit/test_mcp_stdio_smoke.py +0 -68
  107. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/api-documenter.md +0 -0
  108. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/architect-planner.md +0 -0
  109. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/architect-reviewer.md +0 -0
  110. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/code-reviewer.md +0 -0
  111. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/developer.md +0 -0
  112. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/plan-reviewer.md +0 -0
  113. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/sprint-planner.md +0 -0
  114. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  115. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  116. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  117. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/benchmark.yml +0 -0
  118. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/e2e-tests.yml +0 -0
  119. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/release.yml +0 -0
  120. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/test.yml +0 -0
  121. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.gitignore +0 -0
  122. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.pre-commit-config.yaml +0 -0
  123. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.sqlcgignore +0 -0
  124. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/CHANGELOG.md +0 -0
  125. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/CLAUDE.md +0 -0
  126. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/README.md +0 -0
  127. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/docs/AIRBNB_PARSE_REPORT.md +0 -0
  128. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/e2e_firstuser_report.md +0 -0
  129. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/e2e_run_20260528_101413.output +0 -0
  130. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/main.py +0 -0
  131. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/WORKFLOW.md +0 -0
  132. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/blueprint.md +0 -0
  133. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/bundle_claude_skill.md +0 -0
  134. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_34_unused_presentation_segregation.md +0 -0
  135. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_35_external_downstream_injection.md +0 -0
  136. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_F2_bundle_claude_skill.md +0 -0
  137. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_downstream_sink_location.md +0 -0
  138. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_dynamic_table_parsing.md +0 -0
  139. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_expand_qualify_perf.md +0 -0
  140. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_firstuser_findings.md +0 -0
  141. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_schema_case_mismatch.md +0 -0
  142. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/hygiene_config_path_and_survivors.md +0 -0
  143. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/investigation_e5_e4.md +0 -0
  144. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/living_codebase_resync.md +0 -0
  145. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/schema_comparison_with_schema.json +0 -0
  146. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/schema_comparison_without_schema.json +0 -0
  147. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_pool_300s_plan.json +0 -0
  148. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/parse_diagnostics.md +0 -0
  149. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/parsing_errors_experiment.md +0 -0
  150. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/snowflake_en_test_suite.md +0 -0
  151. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_01.md +0 -0
  152. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_01_deployment_pypi.md +0 -0
  153. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_02.md +0 -0
  154. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_02_v0.3.0_core.md +0 -0
  155. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_03.md +0 -0
  156. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_03_v0.3.1_postmortem.md +0 -0
  157. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_04_column_lineage.md +0 -0
  158. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_04_column_lineage_fix.md +0 -0
  159. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_05_star_resolution.md +0 -0
  160. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_06_lineage_coverage.md +0 -0
  161. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_07_open_ecodes.md +0 -0
  162. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_07_perf_and_live_test.md +0 -0
  163. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_08_perf_upsert.md +0 -0
  164. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_09_lineage_coverage.md +0 -0
  165. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_10_anchor_tools.md +0 -0
  166. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_11_v1.0.2_bugfix.md +0 -0
  167. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_12_v1.1.0.md +0 -0
  168. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_13_v1.1.0_cluster_b.md +0 -0
  169. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_3.1_postmortem.md +0 -0
  170. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sqlcg.md +0 -0
  171. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/trust_layer.md +0 -0
  172. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.0_cluster_b_provenance_trust.md +0 -0
  173. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.0_live_graph_freshness.md +0 -0
  174. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.1_batch_upsert_perf.md +0 -0
  175. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_1_2_bugfix.md +0 -0
  176. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_1_3_union_cte_star.md +0 -0
  177. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_2_0_read_proxy.md +0 -0
  178. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_2_1_bugfix.md +0 -0
  179. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/profile.html +0 -0
  180. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/pyrightconfig.json +0 -0
  181. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/scripts/collect_parse_errors.py +0 -0
  182. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/scripts/generate_cli_docs.sh +0 -0
  183. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/__main__.py +0 -0
  184. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/__init__.py +0 -0
  185. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/__init__.py +0 -0
  186. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/install.py +0 -0
  187. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/report.py +0 -0
  188. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/watch.py +0 -0
  189. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/main.py +0 -0
  190. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/jobs.py +0 -0
  191. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/queries.cypher +0 -0
  192. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/schema.cypher +0 -0
  193. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/__init__.py +0 -0
  194. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/dbt_adapter.py +0 -0
  195. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/error_classify.py +0 -0
  196. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/git_delta.py +0 -0
  197. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/pool.py +0 -0
  198. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/walker.py +0 -0
  199. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/watcher.py +0 -0
  200. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/__init__.py +0 -0
  201. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/aggregator.py +0 -0
  202. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/schema_resolver.py +0 -0
  203. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/metrics/__init__.py +0 -0
  204. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/__init__.py +0 -0
  205. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/ansi_parser.py +0 -0
  206. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/base.py +0 -0
  207. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/bigquery_parser.py +0 -0
  208. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/postgres_parser.py +0 -0
  209. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/registry.py +0 -0
  210. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/snowflake_parser.py +0 -0
  211. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/tsql_parser.py +0 -0
  212. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/__init__.py +0 -0
  213. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/exceptions.py +0 -0
  214. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/models.py +0 -0
  215. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/__init__.py +0 -0
  216. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/hashing.py +0 -0
  217. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/ignore.py +0 -0
  218. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/logging.py +0 -0
  219. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/__init__.py +0 -0
  220. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/__init__.py +0 -0
  221. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/adversarial/200_join.sql +0 -0
  222. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/adversarial/500_union.sql +0 -0
  223. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/conftest.py +0 -0
  224. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
  225. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
  226. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
  227. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
  228. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
  229. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
  230. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
  231. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
  232. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
  233. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
  234. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q01.sql +0 -0
  235. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q02.sql +0 -0
  236. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q03.sql +0 -0
  237. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q04.sql +0 -0
  238. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q05.sql +0 -0
  239. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/__init__.py +0 -0
  240. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/conftest.py +0 -0
  241. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_cli_index.py +0 -0
  242. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_git_hook_install.py +0 -0
  243. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
  244. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_watch.py +0 -0
  245. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
  246. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
  247. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
  248. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
  249. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
  250. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_listings.sql +0 -0
  251. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
  252. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_hosts.sql +0 -0
  253. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_listings.sql +0 -0
  254. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_reviews.sql +0 -0
  255. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/bigquery/.gitkeep +0 -0
  256. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/customers.sql +0 -0
  257. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/orders.sql +0 -0
  258. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
  259. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/base_tables.sql +0 -0
  260. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/reports.sql +0 -0
  261. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/views.sql +0 -0
  262. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
  263. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
  264. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
  265. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/etl_star.sql +0 -0
  266. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/base_tables.sql +0 -0
  267. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/reports.sql +0 -0
  268. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/views.sql +0 -0
  269. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/__init__.py +0 -0
  270. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/snowflake/__init__.py +0 -0
  271. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_dialect_matrix.py +0 -0
  272. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_temp_table_lineage.py +0 -0
  273. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/perf/__init__.py +0 -0
  274. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/perf/test_perf.py +0 -0
  275. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E10/__init__.py +0 -0
  276. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E11/__init__.py +0 -0
  277. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/__init__.py +0 -0
  278. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/e12_json_path.sql +0 -0
  279. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
  280. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/test_e12.py +0 -0
  281. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E13/__init__.py +0 -0
  282. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E14/__init__.py +0 -0
  283. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E15/__init__.py +0 -0
  284. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/__init__.py +0 -0
  285. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/e16_merge.sql +0 -0
  286. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
  287. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/test_e16.py +0 -0
  288. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E17/__init__.py +0 -0
  289. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/__init__.py +0 -0
  290. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_decode.sql +0 -0
  291. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
  292. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_nvl2.sql +0 -0
  293. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/test_e18.py +0 -0
  294. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E19/__init__.py +0 -0
  295. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/__init__.py +0 -0
  296. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
  297. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_function_alias.sql +0 -0
  298. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
  299. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/test_e2.py +0 -0
  300. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E20/__init__.py +0 -0
  301. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/__init__.py +0 -0
  302. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
  303. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
  304. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/test_e21.py +0 -0
  305. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E22/__init__.py +0 -0
  306. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/__init__.py +0 -0
  307. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
  308. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
  309. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/test_e23.py +0 -0
  310. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E24/__init__.py +0 -0
  311. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/__init__.py +0 -0
  312. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/e25_cross_db.sql +0 -0
  313. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/e25_two_part.sql +0 -0
  314. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/test_e25.py +0 -0
  315. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/test_e25_full_id.py +0 -0
  316. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E26/__init__.py +0 -0
  317. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/__init__.py +0 -0
  318. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
  319. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/e27_udf.sql +0 -0
  320. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/test_e27.py +0 -0
  321. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E28/__init__.py +0 -0
  322. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E29/__init__.py +0 -0
  323. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/__init__.py +0 -0
  324. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_alter_table.sql +0 -0
  325. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
  326. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
  327. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/test_e3.py +0 -0
  328. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E30/__init__.py +0 -0
  329. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E31/__init__.py +0 -0
  330. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E32/__init__.py +0 -0
  331. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E33/__init__.py +0 -0
  332. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E34/__init__.py +0 -0
  333. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E35/__init__.py +0 -0
  334. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/__init__.py +0 -0
  335. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
  336. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/e36_temp_table.sql +0 -0
  337. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/test_e36.py +0 -0
  338. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/test_e36_xfile.py +0 -0
  339. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E37/__init__.py +0 -0
  340. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E38/__init__.py +0 -0
  341. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/__init__.py +0 -0
  342. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
  343. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
  344. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
  345. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_unpivot.sql +0 -0
  346. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/test_e4.py +0 -0
  347. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/__init__.py +0 -0
  348. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
  349. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
  350. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
  351. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/test_e5.py +0 -0
  352. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
  353. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/__init__.py +0 -0
  354. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
  355. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
  356. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_uuid.sql +0 -0
  357. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/test_e8.py +0 -0
  358. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E9/__init__.py +0 -0
  359. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/__init__.py +0 -0
  360. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
  361. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
  362. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
  363. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
  364. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/__init__.py +0 -0
  365. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
  366. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
  367. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
  368. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
  369. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
  370. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/README.md +0 -0
  371. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/__init__.py +0 -0
  372. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/__init__.py +0 -0
  373. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_etl.sql +0 -0
  374. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
  375. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
  376. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_source.sql +0 -0
  377. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
  378. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
  379. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/conftest.py +0 -0
  380. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/test_plan_review_gates.py +0 -0
  381. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/__init__.py +0 -0
  382. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/snowflake/__init__.py +0 -0
  383. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/snowflake/test_scripting_noise.py +0 -0
  384. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_skill_render.py +0 -0
  385. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_uninstall_skill.py +0 -0
  386. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_01_qualify_once.py +0 -0
  387. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_02_ddl_skip.py +0 -0
  388. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
  389. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_06_log_verbosity.py +0 -0
  390. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T35_config_external_consumers.py +0 -0
  391. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_base_parser.py +0 -0
  392. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_branch_monitor.py +0 -0
  393. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_bulk_upsert_invariant.py +0 -0
  394. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_canonical_target_resolution.py +0 -0
  395. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_cli.py +0 -0
  396. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_cli_help.py +0 -0
  397. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_column_lineage_wiring.py +0 -0
  398. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_config.py +0 -0
  399. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_data_models.py +0 -0
  400. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_dominant_cause.py +0 -0
  401. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_find_cmd.py +0 -0
  402. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_firstuser_findings.py +0 -0
  403. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_freshness_helper.py +0 -0
  404. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_gain_ratio.py +0 -0
  405. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_delta.py +0 -0
  406. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_hooks.py +0 -0
  407. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_graph_backend.py +0 -0
  408. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_hard_kill_pool.py +0 -0
  409. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_indexer_progress.py +0 -0
  410. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_indexer_quality.py +0 -0
  411. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_install.py +0 -0
  412. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_install_message.py +0 -0
  413. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_jobs.py +0 -0
  414. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_judgement.py +0 -0
  415. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_lineage_conversion.py +0 -0
  416. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_literal_column_skip.py +0 -0
  417. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_mcp_best_practices.py +0 -0
  418. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_mcp_control.py +0 -0
  419. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_metrics.py +0 -0
  420. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_noise_filter.py +0 -0
  421. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parse_file_dependency_filter.py +0 -0
  422. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parse_quality.py +0 -0
  423. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parser.py +0 -0
  424. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_perf_scaling_guard.py +0 -0
  425. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_schema_resolver.py +0 -0
  426. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_server.py +0 -0
  427. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
  428. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_sprint_06_t04_t05.py +0 -0
  429. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_star_resolution_unit.py +0 -0
  430. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_submit_feedback.py +0 -0
  431. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_subprocess_isolate.py +0 -0
  432. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_t02_expression_name_extraction.py +0 -0
  433. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_t03_ddl_skip.py +0 -0
  434. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_timeout_cancel.py +0 -0
  435. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_tools_hints.py +0 -0
  436. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_tools_warnings.py +0 -0
  437. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_unqualified_fallback.py +0 -0
  438. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_upsert_batch_invariant.py +0 -0
  439. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_walker.py +0 -0
  440. {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_watcher.py +0 -0
@@ -3026,8 +3026,13 @@ Both are now load-bearing; recorded so a future refactor does not silently undo
3026
3026
  re-verification (80→47 `cte_insert` islands) recorded in the plan; the surviving 47
3027
3027
  are likely legitimately source-less computed measures, not a regression. Shape B of
3028
3028
  the #40 guard now asserts a computed-measure projection so a real gap there reds the guard.
3029
- - **#28 server read-only-by-default + reindex escalation** — out of 1.2.1; recommended
3030
- as a separate minor (1.3.0). The read half is already handled by the v1.2.0 routing proxy.
3029
+ - **#28 server read-only-by-default + reindex escalation** — **IMPLEMENTED in 1.3.0**
3030
+ (#29 single-writer queue + RO→RW escalation; plan
3031
+ [`fix_issue_29_single_writer_queue.md`](plan/fix_issue_29_single_writer_queue.md)).
3032
+ The read half was already handled by the v1.2.0 routing proxy; 1.3.0 adds the write half:
3033
+ the server serves RO after a startup RW schema-ensure window, and escalates RO→RW only for
3034
+ the duration of a single-writer drain. See §20 for the compliance postmortem and two
3035
+ accepted/flagged deviations.
3031
3036
  - **`connected_clients` fidelity** — best-effort `1` today; no real counter.
3032
3037
 
3033
3038
  ## 19. v1.2.1 live DWH re-verification — two residual findings (2026-06-02)
@@ -3145,3 +3150,271 @@ The fix held for v1.2.2 (the helper mirrors the shipped query), but the divergen
3145
3150
  structural. **Future hardening:** replace the string-reconstruction helper with a
3146
3151
  `CliRunner`-based guard that runs the real `analyze downstream` command and asserts the
3147
3152
  rendered output. LOW priority; below §19.1 and the open §3.x items. No plan stub drafted.
3153
+
3154
+ ## 20. v1.3.0 — Single-Writer Queue + RO→RW Escalation (#29 / #28) (2026-06-04)
3155
+
3156
+ Implements the long-deferred §18.4 "#28 server read-only-by-default + reindex escalation"
3157
+ item. Plan: [`fix_issue_29_single_writer_queue.md`](plan/fix_issue_29_single_writer_queue.md).
3158
+ Branch `feat/fix-issue-29-single-writer-queue`, 8 commits (T-01…T-08). Test suite
3159
+ 1009 passed / 7 skipped / 1 xfailed; pyright clean; ruff clean.
3160
+
3161
+ ### 20.1 What shipped (plan-compliance verdict)
3162
+
3163
+ The five phases landed as planned. The hard invariants were honoured **in the
3164
+ control-socket / drain path**:
3165
+
3166
+ - **B1 (no co-existence window)** — Steps 2.2 (drain task + escalation primitive) and 2.3
3167
+ (retire the inline `reindex` op) landed in **one commit** (`62c19cd`). The `reindex` and
3168
+ `index` socket-op handlers in [`server.py`](src/sqlcg/server/server.py) `_control_socket_task`
3169
+ enqueue onto `WriterQueue` and never call `backend_ref()`; the drain task is the sole
3170
+ backend consumer, resolving the backend under `backend_lock` via `escalate_to_rw`.
3171
+ - **B2 (shutdown vs. drain ordering)** — `_stop_watcher`
3172
+ ([`server.py`](src/sqlcg/server/server.py) L394-410) sets `shutdown_requested` then
3173
+ acquires `backend_lock` **before** `shutdown_backend()`; `de_escalate_to_ro`
3174
+ ([`writer.py`](src/sqlcg/server/writer.py)) skips the RO reopen when the event is set.
3175
+ Both guarantees (a)+(b) present.
3176
+ - **B3 (status framing atomic)** — server-side `status` framing (Step 4.1) and the CLI
3177
+ recv-exactly parse (Step 4.2) shipped in one commit (`af2c85d`); `mcp_stop`'s
3178
+ `s.recv(128)` and the unframed `stop` reply are untouched.
3179
+ - **W3 (`from=null`)** — the `reindex` op stores `from_sha=None`; the drain resolves the
3180
+ stored SHA via `rw.get_indexed_sha()` and HEAD via `git rev-parse`, with an actionable
3181
+ "no prior index" error on a never-indexed DB. The CLI refusal was removed.
3182
+ - **W5 (`done:true` sentinel)** — both server emit and CLI recv loops key off
3183
+ `done == true`, not EOF; failure relays `ok:false, done:true, error:…`.
3184
+ - **W6 (`find_lock_holder` public)** — promoted in `kuzu_backend.py`, in-module call site
3185
+ updated, imported by `writer.py`.
3186
+ - **W7 (drain exception handler)** — the drain's `except Exception` clears `_active`
3187
+ (`mark_active_failed`), relays an `ok:false,done:true` terminal frame to waiters, and the
3188
+ loop survives; `EscalationLockError` keeps its dedicated C3 path with the ERROR log.
3189
+
3190
+ ### 20.2 Deviation 1 — MCP `index_repo` tool inline escalation (FLAGGED — follow-up required)
3191
+
3192
+ **What the developer added (not in the plan):** a `_serving_ro` flag +
3193
+ `_get_or_escalate_rw` / `_de_escalate_to_ro_from_tool` helpers in
3194
+ [`tools.py`](src/sqlcg/server/tools.py) so the MCP `index_repo` **tool** (invoked over the
3195
+ stdio transport, distinct from the CLI `index` socket op) escalates RO→RW inline when the
3196
+ server is serving RO.
3197
+
3198
+ **Verdict: the intent is consistent with the single-writer model, but the implementation
3199
+ violates the plan's central invariant and leaks the write lock on failure. Track as a
3200
+ v1.3.x follow-up, not a release blocker (the happy path works and tests are green), but
3201
+ it must be fixed before it is relied on under concurrency.**
3202
+
3203
+ Three concrete problems:
3204
+
3205
+ 1. **Escalation outside `backend_lock` (breaks B1/OD-7).** The plan's load-bearing invariant
3206
+ is "once escalation exists, **no op may operate on a backend resolved outside
3207
+ `backend_lock`**; the only backend consumer is the drain task." The MCP `index_repo` tool
3208
+ escalates and writes with **no lock held** — a second path that can swap
3209
+ `tools._backend` concurrently with a `query` op or a drain. This is exactly the class of
3210
+ bug B1 was written to prevent.
3211
+ 2. **RW-lock leak on the failure path.** `_de_escalate_to_ro_from_tool` is called only on the
3212
+ success branch ([`tools.py`](src/sqlcg/server/tools.py) L613-614), **not in a `finally`**.
3213
+ Any exception during `index_repo` / `upsert_node` / `run_read` / `upsert_edge` re-raises
3214
+ (L634) with the backend still RW — the exclusive write lock stays held, blocking all
3215
+ subsequent routed reads until the server is restarted. (Contrast the drain path, which
3216
+ de-escalates in a `finally`.)
3217
+ 3. **Dead `_set_backend_lock` / `_backend_lock`.** `_set_backend_lock`
3218
+ ([`tools.py`](src/sqlcg/server/tools.py) L117) and the `_backend_lock` global are
3219
+ **defined but never called** — a zero-value stub that looks like the intended lock plumbing
3220
+ for the tool escalation but was never wired. This is the CLAUDE.md "every new method must
3221
+ have a grep-confirmed call site" rule unmet, and the "function defined but never invoked"
3222
+ smell.
3223
+
3224
+ **Follow-up (recommended):** route the MCP `index_repo` tool write through the same
3225
+ `WriterQueue`/drain as the CLI `index` op (so there is genuinely one writer), or — minimally —
3226
+ acquire `backend_lock` for the escalation and move the de-escalation into a `finally`. There
3227
+ is **no test** for this path today (no test references `_get_or_escalate_rw` / `_serving_ro`),
3228
+ so the leak and the lock-bypass are unguarded. A regression test asserting (a) the tool
3229
+ escalates under the lock and (b) a raising `index_repo` de-escalates back to RO is required
3230
+ with the fix.
3231
+
3232
+ ### 20.3 Deviation 2 — Step 4.3 "queued behind N" display (ACCEPTED, minor)
3233
+
3234
+ The plan's Step 4.3 specified that a client queued behind other work prints
3235
+ `queued behind: <op> (done/total files) — position N` before attaching to live progress.
3236
+ The developer implemented the `done:true` terminal sentinel and the progress-bar attach
3237
+ fully, but **omitted the "queued behind … position N" pre-active display**: the CLI receives
3238
+ the `{queued:true, position:N}` frame and the subsequent progress frames, but the queued
3239
+ frame is silently consumed (it carries no `files_total`, so the progress loop renders
3240
+ nothing for it) — see [`index.py`](src/sqlcg/cli/commands/index.py) L307-311.
3241
+
3242
+ **Verdict: ACCEPTED as a cosmetic shortfall.** The functional contract (enqueue, attach,
3243
+ stream progress, terminate on `done:true`, exit non-zero on `ok:false`) is intact; only the
3244
+ human-readable "you are behind N others" hint is missing. The `position` is already on the
3245
+ wire, so completing it is a one-line render in the existing loop. Track as a polish item,
3246
+ not a correctness gap.
3247
+
3248
+ ### 20.4 Test-coverage gaps vs. the plan's Test Strategy (FLAGGED)
3249
+
3250
+ The plan's Test Strategy enumerated several **deterministic** integration tests that were
3251
+ not implemented as test functions, even though
3252
+ [`test_single_writer_queue.py`](tests/integration/test_single_writer_queue.py)'s module
3253
+ docstring lists B2 / W3 among its coverage (the docstring overstates what is asserted):
3254
+
3255
+ - **B2 stop-mid-drain** (in-flight write commits; `tools._backend is None` after shutdown,
3256
+ no reopen-after-shutdown) — listed in the docstring, **no test function**.
3257
+ - **W3** arg-level assertion (`resync_changed(from=stored SHA, to=HEAD)`) and the
3258
+ never-indexed "no prior index" error — **no test** (the drain code is present and exercised
3259
+ indirectly by Scenario A, but the W3-specific arg/branch assertions are missing).
3260
+ - **W7** drain-body-raises → `_active` cleared + `ok:false,done:true` terminal frame + loop
3261
+ survives — **no test**.
3262
+ - **Reads block during a drain** (OD-1, deterministic `anyio.Event` ordering) — **no test**.
3263
+ - **B1 structural guard** (the `reindex` op body contains no pre-lock `backend_ref()`,
3264
+ mirroring the perf-invariant guard discipline) — **no test**.
3265
+ - **Escalation transition on real Kuzu** (second in-process RO holder forces
3266
+ `EscalationLockError`) — **no test** (only the injected-`opener` unit tests cover retry).
3267
+
3268
+ What **is** covered: fresh-DB init, stale-schema refusal (Step 1.4), `db reset` refusal
3269
+ (Step 3.4), framed `status` + `writer_queue` shape (Steps 4.1/4.2), metrics persisted +
3270
+ `SQLCG_METRICS=0` suppression (Step 4.5), the escalation retry/backoff + ERROR-log unit tests
3271
+ (Steps 1.2/4.4), the coalescing rules (Step 2.1), and the drain-runs-`resync_changed`-once
3272
+ invariant guard (Scenario A in `test_reindex_via_server.py`).
3273
+
3274
+ **Verdict:** these are real plan deviations (the named deterministic guards were specified
3275
+ and not delivered), but the shipped behaviour is exercised indirectly and the suite is green,
3276
+ so they are **follow-up hardening**, not a ship blocker. They should be filed alongside the
3277
+ Deviation-1 fix — the B2/W7/reads-block tests in particular guard the exact concurrency
3278
+ contract that Deviation 1 currently bypasses.
3279
+
3280
+ ---
3281
+
3282
+ ## Kuzu → DuckDB Migration — Architecture Review (2026-06-05, v1.4.0)
3283
+
3284
+ Reviewed `git diff master..HEAD` on `feat/duckdb-migration` (9 commits, 91 files,
3285
+ ~3885+/2782-). Plan: [`plan/feature_kuzu_to_duckdb_migration.md`](plan/feature_kuzu_to_duckdb_migration.md).
3286
+
3287
+ ### Conformance verdict: SHIP (1 documentation fix + 1 dead-code cleanup recommended)
3288
+
3289
+ Phases 1–5 delivered the specified deliverables. All five Phase-5 exit gates are met:
3290
+ the live DWH acceptance gate (index 1,391 files ~2.5 min; reindex ×3 no crash; column
3291
+ trace) passed today; perf guards green; parity fixture committed; symbol-deletion clean.
3292
+ Two non-blocking gaps (see below).
3293
+
3294
+ ### Plan conformance — deliverable check
3295
+
3296
+ | Phase | Status | Notes |
3297
+ |---|---|---|
3298
+ | 1 — backend skeleton + schema | **PASS** | [`duckdb_backend.py`](src/sqlcg/core/duckdb_backend.py): 7 node + 12 edge tables, src/dst indexes, idempotent `init_schema` in one txn, real reentrant `transaction()`. |
3299
+ | 2 — bulk-upsert sink | **PASS** | `upsert_nodes_bulk`/`upsert_edges_bulk` via `INSERT OR REPLACE … SELECT unnest(?)` — one `execute()` per label/rel per batch. `_flush_row_batch` per-batch shape unchanged ([`indexer.py:90`](src/sqlcg/indexer/indexer.py)). |
3300
+ | 3 — query port + parity | **PASS** | Recursive-CTE traversal with depth + cycle guard ([`analyze.py:38`](src/sqlcg/cli/commands/analyze.py)); kind-filter ported as `LEFT JOIN … WHERE kind IS NULL OR IN ('table','external')`; parity fixture + test committed ([`tests/integration/test_duckdb_parity.py`](tests/integration/test_duckdb_parity.py)). `execute_cypher`→`execute_sql` renamed ([`tools.py:1616`](src/sqlcg/server/tools.py)). |
3301
+ | 4 — rebuild-in-transaction | **PASS (with deviation, see Concurrency)** | Drain body `with backend.transaction(): clear_all_tables(); index_repo()` ([`writer.py:363`](src/sqlcg/server/writer.py)); escalation machinery deleted; single R/W handle. |
3302
+ | 5 — cutover + perf | **PASS** | `kuzu_backend.py`/`neo4j_backend.py` deleted; `KuzuConfig`→`DbConfig` ([`config.py:14`](src/sqlcg/core/config.py)); `buffer_pool` flags removed; `uninstall.py` uses `Path.unlink` + `.wal` ([`uninstall.py:113`](src/sqlcg/cli/commands/uninstall.py)); version 1.4.0; kuzu/neo4j deps dropped. |
3303
+
3304
+ **Gaps (non-blocking):**
3305
+ 1. **Dead Kuzu fallback in the happy path** — [`indexer.py:1393–1423`](src/sqlcg/indexer/indexer.py)
3306
+ `_expand_star_sources` keeps a `# Fallback path for Kuzu legacy backend` branch with inline
3307
+ Cypher `MERGE` strings. Kuzu is deleted, so this branch is unreachable dead code that still
3308
+ references a removed backend's dialect. Plan Tier-1 said cutover removes Kuzu-only code; this
3309
+ is a leftover. Recommend deleting the `else` branch and the `isinstance(db, DuckDBBackend)`
3310
+ guard (the only backend is DuckDB). Not a ship blocker (the live path is the DuckDB branch),
3311
+ but it is exactly the "TODO/stub in the success path" class CLAUDE.md warns against.
3312
+ 2. **`tests/e2e/test_dwh_e2e.py`** migrated on disk but never committed (correct per MEMORY:
3313
+ feedback_dwh_e2e — gitignored). The double-reindex/perf acceptance was run manually today;
3314
+ there is no committed CI guard for it. Accept (matches existing project policy).
3315
+
3316
+ ### Performance invariants — pass/fail (CLAUDE.md table)
3317
+
3318
+ All guard tests green: `test_perf_scaling_guard`, `test_upsert_batch_invariant`,
3319
+ `test_bulk_upsert_invariant`, `test_T09_01_qualify_once` (11 passed).
3320
+
3321
+ | Invariant | Verdict | Evidence |
3322
+ |---|---|---|
3323
+ | `qualify`/`build_scope` module-level import | **PASS** | `base.py` untouched (parser-side, backend-agnostic). |
3324
+ | `exp.expand()` file-level sources + `dependency_filter` | **PASS** | parser-side, untouched. |
3325
+ | `body_scope` built once per statement | **PASS** | untouched. |
3326
+ | Pure-literal skip | **PASS** | untouched. |
3327
+ | No `sources=` when scope present / `copy=False`+`trim_selects=False` | **PASS** | untouched. |
3328
+ | INSERT body copied once | **PASS** | untouched. |
3329
+ | `_upsert_parsed_file` uses bulk (not per-row) | **PASS** | sink re-pointed to `upsert_*_bulk`; no per-row path in flush. |
3330
+ | `_flush_row_batch` once-per-batch (not per-file) | **PASS** | [`indexer.py:162–176`](src/sqlcg/indexer/indexer.py): exactly 10 bulk calls per batch; DuckDB `upsert_*_bulk` issues **one** `execute()` per call ([`duckdb_backend.py:412`,`456`](src/sqlcg/core/duckdb_backend.py)). |
3331
+
3332
+ **No reintroduced O(N²):** the bulk sink uses array-parameter `unnest`, one round-trip per
3333
+ label/rel. Read CTEs carry `WHERE reach.depth < d` + `NOT key = ANY(reach.path)` cycle guard
3334
+ ([`analyze.py:57–58`](src/sqlcg/cli/commands/analyze.py)). `delete_nodes_for_file` is
3335
+ set-based DELETEs, no per-row loop. Edge tables indexed on both `src_key` and `dst_key`.
3336
+ One watch item: `array_append`/`= ANY(path)` cycle guard is O(path-length) per row, acceptable
3337
+ at depth≤100 but is the only place traversal cost grows with path depth — bounded by the depth cap.
3338
+
3339
+ ### Concurrency model — assessment
3340
+
3341
+ **Reentrant `transaction()` ([`duckdb_backend.py:723`](src/sqlcg/core/duckdb_backend.py)):
3342
+ correct.** Depth-counted; only the outermost level emits BEGIN/COMMIT/ROLLBACK; nested calls
3343
+ join and re-raise so a failure anywhere rolls back the whole rebuild. This lets the drain wrap
3344
+ `clear_all_tables()` + `index_repo()` (which opens its own per-batch transactions) in one atomic
3345
+ unit. Verified by `test_mvcc_rebuild.py` (3 passed) and the C6 unit test.
3346
+
3347
+ **`clear_all_tables()` preserving `SchemaVersion`: right call.** It truncates all node/edge
3348
+ tables but leaves the `SchemaVersion` row so the schema-gate survives a rebuild and
3349
+ `indexed_sha` is re-stamped by the indexer inside the same transaction
3350
+ ([`indexer.py:504`](src/sqlcg/indexer/indexer.py)) — the SHA flips atomically with the graph.
3351
+
3352
+ **DEVIATION — "readers never block" is not what shipped (but what shipped is SAFE).**
3353
+ The plan/design (§Concurrency, C3) sells DuckDB MVCC: readers on separate cursors see the OLD
3354
+ snapshot during a write txn and flip on COMMIT, so reads never block. The implementation does
3355
+ **not** use `con.cursor()` per read — `run_read` executes on the **single shared `self._conn`**
3356
+ ([`duckdb_backend.py:476`](src/sqlcg/core/duckdb_backend.py)), and the server serializes every
3357
+ read and the drain through one `anyio` `backend_lock` ([`server.py:347`](src/sqlcg/server/server.py),
3358
+ [`writer.py:330`](src/sqlcg/server/writer.py)). Net effect: a `query` arriving mid-rebuild
3359
+ **waits** for the rebuild to finish rather than being served the old snapshot. This is *safe*
3360
+ (no torn read — the lock prevents a read on a connection with an open uncommitted BEGIN), but
3361
+ it forfeits the headline MVCC non-blocking-read benefit. For the full-rebuild path that holds
3362
+ the lock for the entire ~2.5 min index, **reads are unavailable for the rebuild duration.**
3363
+ Action: fix the plan/docstring claim, OR (better, follow-up) serve reads from `self._conn.cursor()`
3364
+ and drop the read side of `backend_lock` to realize the promised non-blocking reads.
3365
+
3366
+ **Long-transaction risk in the drain body (lock duration / memory / partial-failure):**
3367
+ - *Lock duration:* the full rebuild holds both the OS-level DuckDB file lock and the in-process
3368
+ `backend_lock` for the entire index (~2.5 min on the DWH). Cross-process this is fine (single
3369
+ writer by design); in-process it blocks reads (above). Acceptable for a full rebuild; the real
3370
+ fix is incremental reindex (Option 2, explicitly deferred).
3371
+ - *Memory:* one transaction spanning `clear_all_tables()` + all batch inserts means DuckDB holds
3372
+ the rebuild's undo/WAL state until COMMIT. The plan's batch loop still runs, but per-batch
3373
+ transactions are **subsumed** into the outer txn (reentrancy makes them no-ops), so there is
3374
+ **no intermediate commit** — the OOM-prevention intent of `batch_size` is about parse working-set,
3375
+ not write durability, so this is consistent with CLAUDE.md, but worth noting: write-side memory
3376
+ is now one-transaction-wide, not one-batch-wide. The DWH (47k columns, 45k edges) committed in
3377
+ ~2.5 min with no OOM, so empirically fine at current scale; flag for the 1,600-file ceiling.
3378
+ - *Partial-failure:* correct — a mid-rebuild raise rolls back to the prior graph (C6, tested).
3379
+ Better than the old swap's corruption window.
3380
+
3381
+ ### Backend abstraction — assessment (no action requested)
3382
+
3383
+ With kuzu/neo4j deleted, `GraphBackend` is a **single-impl ABC** — it now adds indirection
3384
+ without polymorphism. It still earns partial keep: (a) tests use an in-memory `:memory:`
3385
+ DuckDBBackend through the same interface; (b) the documented v2 roadmap (Snowflake
3386
+ ACCESS_HISTORY as a second lineage source) may want a second backend. But several smells:
3387
+ - ABC docstrings still say "Cypher for KùzuDB/Neo4j" ([`graph_db.py:121,133`](src/sqlcg/core/graph_db.py))
3388
+ and "skipped by KuzuDB's MERGE semantics" (line 105) — stale, misleading now.
3389
+ - `clear_all_tables()` on the ABC with a `NotImplementedError` default ([`graph_db.py:248`](src/sqlcg/core/graph_db.py))
3390
+ is the wrong shape now that only DuckDB implements it: a `NotImplementedError`-default method on
3391
+ an ABC is a code smell (it is neither abstract-required nor universally provided). With one impl,
3392
+ it should either be a plain method on `DuckDBBackend` (not on the ABC) or a proper `@abstractmethod`.
3393
+ Recommend: move it off the ABC, or make it abstract. Low priority — cosmetic, single caller.
3394
+ - `transaction()`'s ABC no-op default that "logs a warning" is now dead (only DuckDB, which
3395
+ overrides). Harmless.
3396
+
3397
+ **Recommendation (do not act now):** keep the ABC for the v2 second-source path, but schedule a
3398
+ docstring de-Cypher pass and relocate `clear_all_tables` off the ABC. If v2 ACCESS_HISTORY is
3399
+ shelved, collapse the ABC into `DuckDBBackend` directly.
3400
+
3401
+ ### Release risk register for 1.4.0 (ranked likelihood × impact)
3402
+
3403
+ 1. **Reads blocked for the full ~2.5 min rebuild duration (HIGH likelihood × MED impact).**
3404
+ The serialized single-connection model means MCP/CLI reads hang while a full `index`/`reindex`
3405
+ drains. On the DWH that is ~2.5 min of read unavailability per rebuild. Users expecting the
3406
+ plan's "non-blocking reads" will see hangs. Mitigation: cursor-per-read follow-up; for now,
3407
+ document the behavior and rely on rebuild infrequency.
3408
+ 2. **Dead Kuzu fallback branch ([`indexer.py:1393`](src/sqlcg/indexer/indexer.py)) (MED × LOW).**
3409
+ Unreachable but references a deleted backend; a future reader may mistake it for a live path,
3410
+ and it carries Cypher that no longer has an engine. Delete before/just after release.
3411
+ 3. **One-transaction-wide write memory at the 1,600-file ceiling (LOW × MED).**
3412
+ Proven fine at DWH scale (1,391 files); the CLAUDE.md target tops out at ~1,600. The whole
3413
+ rebuild is one DuckDB transaction (per-batch commits subsumed), so peak WAL/undo is the full
3414
+ graph. Measure headroom at 1,600 before declaring the perf budget closed.
3415
+ 4. **No committed CI guard for double-reindex / perf (LOW × MED).**
3416
+ The headline acceptance (double-reindex no-crash + lineage parity) was validated manually via
3417
+ the gitignored e2e test. A regression would not be caught in CI. Accept per project policy, but
3418
+ the committed `test_mvcc_rebuild.py` + parity fixture partially cover the rebuild path.
3419
+ 5. **Stale "Cypher/Kuzu" references in docstrings/comments across server + indexer (LOW × LOW).**
3420
+ Cosmetic; misleads future maintainers about the engine. Sweep in a docs pass.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-code-graph
3
- Version: 1.2.2
3
+ Version: 1.4.0
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
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Topic :: Database
19
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Python: >=3.12
21
- Requires-Dist: kuzu==0.11.3
21
+ Requires-Dist: duckdb<2.0,>=1.0.0
22
22
  Requires-Dist: mcp<2.0,>=1.27.0
23
23
  Requires-Dist: pathspec>=0.12.1
24
24
  Requires-Dist: pydantic>=2.0
@@ -30,8 +30,6 @@ Requires-Dist: typer>=0.9.0
30
30
  Requires-Dist: watchdog>=3.0.0
31
31
  Provides-Extra: dbt
32
32
  Requires-Dist: dbt-core>=1.7; extra == 'dbt'
33
- Provides-Extra: neo4j
34
- Requires-Dist: neo4j>=5.15.0; extra == 'neo4j'
35
33
  Provides-Extra: snowflake
36
34
  Requires-Dist: acryl-datahub<0.15.0,>=0.14.0; extra == 'snowflake'
37
35
  Description-Content-Type: text/markdown
@@ -62,6 +62,13 @@ sqlcg index [OPTIONS] PATH
62
62
 
63
63
  Index SQL files in a directory.
64
64
 
65
+ When a server is live on this DB, the index is routed through the server's
66
+ control socket so the DB is never opened directly (avoids lock contention).
67
+ Use --detach to enqueue and return immediately (fire-and-forget).
68
+
69
+ With no server live, falls back to the direct-write path unchanged
70
+ (zero-config small-repo invariant).
71
+
65
72
  Schema aliases (staging schema → canonical schema) can be configured in
66
73
  .sqlcg.toml under sqlcg.schema_aliases, e.g. da_tmp = "da".
67
74
 
@@ -72,14 +79,14 @@ Schema aliases (staging schema → canonical schema) can be configured in
72
79
  | --dialect, -d | TEXT | No | No | | SQL dialect (or 'auto' to read from .sqlcg.toml) |
73
80
  | --dbt-manifest | PATH | No | No | | Path to dbt manifest |
74
81
  | --timeout-per-file | INTEGER | No | No | 10 | Timeout per file in seconds |
75
- | --buffer-pool-size | INTEGER | No | No | 0 | KuzuDB buffer pool size in MB (0 = default). Set to 256-512 on memory-constrained machines. |
76
- | --batch-size | INTEGER | No | No | 50 | Files per KuzuDB transaction in the upsert pass. Default 50 balances commit-overhead reduction (vs. legacy per-file commits) against per-batch memory cost. Lower values are safer for memory-constrained machines; higher values give marginal speedup at the cost of larger working sets. Set to 1 to reproduce legacy per-file commit behaviour. |
82
+ | --batch-size | INTEGER | No | No | 50 | Files per DuckDB transaction in the upsert pass. Default 50 balances commit-overhead reduction (vs. legacy per-file commits) against per-batch memory cost. Lower values are safer for memory-constrained machines; higher values give marginal speedup at the cost of larger working sets. Set to 1 to reproduce legacy per-file commit behaviour. |
77
83
  | --no-ddl | BOOLEAN | No | No | False | Skip table-node upserts for DDL-only files |
78
84
  | --quiet, -q | BOOLEAN | No | No | False | Suppress summary console output |
79
85
  | --verbose, -v | BOOLEAN | No | No | False | Print parse warnings to stderr instead of log file |
80
86
  | --debug | BOOLEAN | No | No | False | Show detailed log output during indexing |
81
87
  | --profile / --no-profile | BOOLEAN | No | No | False | Emit per-stage timing after indexing |
82
88
  | --include-working-tree | BOOLEAN | No | No | False | Index the working tree including uncommitted changes. Marks freshness as 'indexed with working-tree changes'. |
89
+ | --detach | BOOLEAN | No | No | False | When routing through a live server, return immediately after enqueueing (fire-and-forget). Default is to wait for the index to complete. |
83
90
 
84
91
  ## `sqlcg reindex`
85
92
 
@@ -211,7 +218,7 @@ sqlcg uninstall [OPTIONS]
211
218
  Uninstall sqlcg from Claude Code and optionally clean up resources.
212
219
 
213
220
  Step 1: Remove MCP registration from ~/.claude/settings.json
214
- Step 2: Optionally delete the KùzuDB graph database
221
+ Step 2: Optionally delete the DuckDB graph database
215
222
  Step 3: Remove git hook sentinel block from .git/hooks/post-checkout
216
223
  Step 4: Remove sqlcg skill directory from ~/.claude/skills/sqlcg/ and
217
224
  <repo>/.claude/skills/sqlcg/
@@ -267,7 +274,7 @@ Initialise the graph database (idempotent).
267
274
 
268
275
  | Option | Type | Required | Repeatable | Default | Description |
269
276
  | --- | --- | --- | --- | --- | --- |
270
- | --buffer-pool-size | INTEGER | No | No | 0 | KuzuDB buffer pool size in MB (0 = default). Set to 256-512 on memory-constrained machines. |
277
+ | _none_ | | | | | |
271
278
 
272
279
  ## `sqlcg db reset`
273
280
 
@@ -441,13 +448,6 @@ sqlcg analyze failures [OPTIONS]
441
448
 
442
449
  List files that failed to parse, with their dominant cause (E-code bucket).
443
450
 
444
- Valid --cause buckets (from highest to lowest severity):
445
- timeout, E8, E3, E2, E5, E1, qualify_failed, func_fallback, pure_ddl_skip.
446
-
447
- Requires a graph indexed with sqlcg >= v3 (schema version 3). Re-index
448
- with 'sqlcg db reset && sqlcg index <path>' if the graph was built with
449
- an earlier version.
450
-
451
451
  ### Options
452
452
 
453
453
  | Option | Type | Required | Repeatable | Default | Description |
@@ -548,7 +548,12 @@ sqlcg mcp status [OPTIONS]
548
548
  Print server status JSON (connects to control socket).
549
549
 
550
550
  Returns JSON with fields: running, pid, db_path, indexed_sha, head_sha,
551
- stale_by_commits, connected_clients, uptime when a server is live.
551
+ stale_by_commits, connected_clients, uptime, writer_queue when a server
552
+ is live.
553
+
554
+ The status response is length-prefixed framed (v1.3.0, B3) so large
555
+ writer_queue payloads are received in full — the client uses the
556
+ recv-exactly makefile+readline+read(n) pattern, NOT a single recv(4096).
552
557
 
553
558
  When no server is found: {"running": false}.
554
559
  When the PID file exists with a live process but the socket is unavailable: