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.
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/ARCHITECTURE_REVIEW.md +275 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/PKG-INFO +2 -4
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/docs/cli.md +17 -12
- sql_code_graph-1.4.0/plan/feature_kuzu_to_duckdb_migration.md +541 -0
- sql_code_graph-1.4.0/plan/fix_issue29_live_test_followups.md +442 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_08_changelogs_fullindex.json +14 -14
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_08_fullcorpus_index.json +15 -15
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/pyproject.toml +2 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/__init__.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/analyze.py +138 -127
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/db.py +49 -51
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/find.py +5 -9
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/gain.py +14 -16
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/git.py +11 -4
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/index.py +173 -21
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/mcp.py +70 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/reindex.py +147 -77
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/uninstall.py +9 -20
- sql_code_graph-1.4.0/src/sqlcg/core/__init__.py +6 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/config.py +25 -81
- sql_code_graph-1.4.0/src/sqlcg/core/duckdb_backend.py +764 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/freshness.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/graph_db.py +20 -4
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/queries.py +26 -7
- sql_code_graph-1.4.0/src/sqlcg/core/queries.sql +249 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/schema.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/indexer.py +27 -36
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/metrics/store.py +49 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/control.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/noise_filter.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/read_client.py +2 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/server.py +184 -86
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/skill.py +2 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/tools.py +119 -41
- sql_code_graph-1.4.0/src/sqlcg/server/writer.py +459 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/bench_indexer.py +3 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_F2_skill_install_e2e.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_airbnb_e2e.py +20 -21
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_golden_lineage.py +23 -27
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_mcp_lifecycle.py +29 -9
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_mcp_tools.py +32 -37
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_star_resolution_e2e.py +10 -10
- sql_code_graph-1.4.0/tests/fixtures/duckdb_parity/kuzu_reference.json +146 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/snowflake/test_insert_select.py +8 -7
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_T34_presentation_segregation.py +3 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_T35_external_consumers.py +19 -20
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_anchor_tools.py +3 -3
- sql_code_graph-1.4.0/tests/integration/test_bulk_upsert.py +150 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_column_lineage_e2e.py +3 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cross_file_lineage.py +9 -9
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_recall_guard.py +22 -22
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_schema_alias_guard.py +21 -28
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_cte_source_node_invariant.py +11 -11
- sql_code_graph-1.4.0/tests/integration/test_dialect_auto_resolution.py +178 -0
- sql_code_graph-1.4.0/tests/integration/test_duckdb_parity.py +246 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_e36_xfile_regression_guard.py +8 -8
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_freshness_mcp.py +9 -46
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_hygiene_config_root_reconciliation.py +3 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_batching.py +26 -29
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_commits.py +3 -20
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_indexer_to_graph.py +15 -8
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_live_anchors.py +19 -16
- sql_code_graph-1.4.0/tests/integration/test_mvcc_rebuild.py +220 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_parse_diagnostics.py +8 -8
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr1_confidence_reason.py +3 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr2_source_location.py +14 -14
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_pr3_kind_tagging.py +8 -6
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_read_via_server.py +35 -28
- sql_code_graph-1.4.0/tests/integration/test_readonly_under_lock.py +281 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_reindex_via_server.py +72 -39
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_resync.py +17 -16
- sql_code_graph-1.4.0/tests/integration/test_single_writer_queue.py +394 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_star_resolution.py +37 -33
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_union_cte_star_recall_guard.py +17 -25
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_user_surface_recall_guard.py +17 -38
- sql_code_graph-1.4.0/tests/unit/test_BugB_escalation_uses_init_path.py +86 -0
- sql_code_graph-1.4.0/tests/unit/test_BugC_hook_upgrade.py +184 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_install_skill.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_aggregator.py +2 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_aggregator_skip.py +2 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_closure_depth.py +8 -8
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_db_info.py +27 -17
- sql_code_graph-1.4.0/tests/unit/test_duckdb_backend.py +423 -0
- 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
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_hooks_notify.py +29 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_hygiene_config_warning.py +0 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_include_working_tree.py +0 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_cmd.py +0 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_flags.py +0 -3
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_index_progress.py +3 -3
- sql_code_graph-1.4.0/tests/unit/test_mcp_stdio_smoke.py +76 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_pr07_observability.py +6 -6
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_queries_loader.py +23 -25
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_read_client.py +1 -1
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +2 -2
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_star_schema_unit.py +17 -15
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_uninstall.py +42 -45
- sql_code_graph-1.4.0/tests/unit/test_writer_queue.py +207 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/uv.lock +33 -44
- sql_code_graph-1.2.2/src/sqlcg/core/__init__.py +0 -8
- sql_code_graph-1.2.2/src/sqlcg/core/kuzu_backend.py +0 -445
- sql_code_graph-1.2.2/src/sqlcg/core/neo4j_backend.py +0 -233
- sql_code_graph-1.2.2/tests/integration/test_bulk_upsert.py +0 -255
- sql_code_graph-1.2.2/tests/integration/test_readonly_under_lock.py +0 -419
- sql_code_graph-1.2.2/tests/unit/test_kuzu_lock.py +0 -91
- sql_code_graph-1.2.2/tests/unit/test_mcp_stdio_smoke.py +0 -68
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/api-documenter.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/architect-planner.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/architect-reviewer.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/code-reviewer.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/developer.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/plan-reviewer.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.claude/agents/sprint-planner.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/benchmark.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/e2e-tests.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/release.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.github/workflows/test.yml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.gitignore +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.pre-commit-config.yaml +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/.sqlcgignore +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/CHANGELOG.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/CLAUDE.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/README.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/docs/AIRBNB_PARSE_REPORT.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/e2e_firstuser_report.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/e2e_run_20260528_101413.output +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/main.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/WORKFLOW.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/blueprint.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/bundle_claude_skill.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_34_unused_presentation_segregation.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_35_external_downstream_injection.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/feature_F2_bundle_claude_skill.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_downstream_sink_location.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_dynamic_table_parsing.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_expand_qualify_perf.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_firstuser_findings.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/fix_schema_case_mismatch.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/hygiene_config_path_and_survivors.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/investigation_e5_e4.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/living_codebase_resync.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/schema_comparison_with_schema.json +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/schema_comparison_without_schema.json +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/measurements/sprint_pool_300s_plan.json +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/parse_diagnostics.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/parsing_errors_experiment.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/snowflake_en_test_suite.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_01.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_01_deployment_pypi.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_02.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_02_v0.3.0_core.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_03.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_03_v0.3.1_postmortem.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_04_column_lineage.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_04_column_lineage_fix.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_05_star_resolution.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_06_lineage_coverage.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_07_open_ecodes.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_07_perf_and_live_test.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_08_perf_upsert.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_09_lineage_coverage.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_10_anchor_tools.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_11_v1.0.2_bugfix.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_12_v1.1.0.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_13_v1.1.0_cluster_b.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sprint_3.1_postmortem.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/sqlcg.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/trust_layer.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.0_cluster_b_provenance_trust.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.0_live_graph_freshness.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1.1.1_batch_upsert_perf.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_1_2_bugfix.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_1_3_union_cte_star.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_2_0_read_proxy.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/plan/v1_2_1_bugfix.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/profile.html +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/pyrightconfig.json +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/scripts/collect_parse_errors.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/scripts/generate_cli_docs.sh +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/__main__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/install.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/report.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/commands/watch.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/cli/main.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/jobs.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/queries.cypher +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/core/schema.cypher +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/dbt_adapter.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/error_classify.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/git_delta.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/pool.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/walker.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/indexer/watcher.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/aggregator.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/lineage/schema_resolver.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/metrics/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/ansi_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/base.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/bigquery_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/postgres_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/registry.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/snowflake_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/parsers/tsql_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/exceptions.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/server/models.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/hashing.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/ignore.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/src/sqlcg/utils/logging.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/adversarial/200_join.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/adversarial/500_union.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/conftest.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q01.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q02.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q03.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q04.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/benchmarks/tpch/q05.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/conftest.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_cli_index.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_git_hook_install.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/e2e/test_watch.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_listings.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_hosts.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_listings.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/airbnb/src_reviews.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/bigquery/.gitkeep +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/customers.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/orders.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/base_tables.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/reports.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/snowflake/views.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/star_corpus/etl_star.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/base_tables.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/reports.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/fixtures/synthetic/views.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/snowflake/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_dialect_matrix.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/integration/test_temp_table_lineage.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/perf/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/perf/test_perf.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E10/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E11/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/e12_json_path.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E12/test_e12.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E13/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E14/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E15/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/e16_merge.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E16/test_e16.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E17/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_decode.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/e18_nvl2.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E18/test_e18.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E19/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_function_alias.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E2/test_e2.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E20/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E21/test_e21.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E22/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E23/test_e23.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E24/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/e25_cross_db.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/e25_two_part.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/test_e25.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E25/test_e25_full_id.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E26/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/e27_udf.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E27/test_e27.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E28/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E29/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_alter_table.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E3/test_e3.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E30/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E31/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E32/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E33/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E34/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E35/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/e36_temp_table.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/test_e36.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E36/test_e36_xfile.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E37/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E38/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/e4_unpivot.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E4/test_e4.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/test_e5.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/e8_uuid.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E8/test_e8.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E9/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/README.md +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_etl.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/fixture_source.sql +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/conftest.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/snowflake/test_plan_review_gates.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/snowflake/__init__.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/snowflake/test_scripting_noise.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_skill_render.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_F2_uninstall_skill.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_01_qualify_once.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_02_ddl_skip.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T09_06_log_verbosity.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_T35_config_external_consumers.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_base_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_branch_monitor.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_bulk_upsert_invariant.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_canonical_target_resolution.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_cli.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_cli_help.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_column_lineage_wiring.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_config.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_data_models.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_dominant_cause.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_find_cmd.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_firstuser_findings.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_freshness_helper.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_gain_ratio.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_delta.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_git_hooks.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_graph_backend.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_hard_kill_pool.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_indexer_progress.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_indexer_quality.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_install.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_install_message.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_jobs.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_judgement.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_lineage_conversion.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_literal_column_skip.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_mcp_best_practices.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_mcp_control.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_metrics.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_noise_filter.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parse_file_dependency_filter.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parse_quality.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_parser.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_perf_scaling_guard.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_schema_resolver.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_server.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_sprint_06_t04_t05.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_star_resolution_unit.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_submit_feedback.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_subprocess_isolate.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_t02_expression_name_extraction.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_t03_ddl_skip.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_timeout_cancel.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_tools_hints.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_tools_warnings.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_unqualified_fallback.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_upsert_batch_invariant.py +0 -0
- {sql_code_graph-1.2.2 → sql_code_graph-1.4.0}/tests/unit/test_walker.py +0 -0
- {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** —
|
|
3030
|
-
|
|
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.
|
|
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:
|
|
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
|
-
| --
|
|
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
|
|
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
|
-
|
|
|
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
|
|
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:
|