sql-code-graph 1.33.0__tar.gz → 1.34.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.33.0 → sql_code_graph-1.34.0}/PKG-INFO +1 -1
- sql_code_graph-1.34.0/plan/metrics/lineage5_dwh_after_pr5.json +9 -0
- sql_code_graph-1.34.0/plan/metrics/lineage5_dwh_before_master.json +6 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/pyproject.toml +1 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/__init__.py +1 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/duckdb_backend.py +46 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/graph_db.py +10 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/queries.py +2 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/queries.sql +47 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/schema.py +2 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/indexer.py +67 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/ansi_parser.py +2 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/base.py +88 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/tools.py +10 -6
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_T35_external_consumers.py +2 -2
- sql_code_graph-1.34.0/tests/integration/test_impact_consumer_parity.py +230 -0
- sql_code_graph-1.34.0/tests/integration/test_join_col_resolution.py +392 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_parse_diagnostics.py +1 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_pr2_source_location.py +3 -3
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_pr_impact_integration.py +70 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_qualify_failed_persist.py +6 -5
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_skip_counts_integration.py +3 -3
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_tool_version_stamp_integration.py +11 -10
- sql_code_graph-1.34.0/tests/unit/test_join_col_resolve_marker.py +103 -0
- sql_code_graph-1.34.0/tests/unit/test_resolve_join_columns_sql.py +146 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_star_schema_unit.py +6 -5
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/uv.lock +1 -1
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/api-documenter.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/architect-planner.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/architect-reviewer.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/code-reviewer.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/developer.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/plan-reviewer.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.claude/agents/sprint-planner.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/workflows/benchmark.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/workflows/e2e-tests.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/workflows/release.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.github/workflows/test.yml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.gitignore +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.pre-commit-config.yaml +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/.sqlcgignore +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/ARCHITECTURE_REVIEW.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/ARCHITECTURE_REVIEW_ARCHIVE.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/CHANGELOG.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/CLAUDE.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/README.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/docs/AIRBNB_PARSE_REPORT.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/docs/cli.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/docs/getting-started.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/docs/releasing-pypi.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/e2e_firstuser_report.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/e2e_run_20260528_101413.output +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/main.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/WORKFLOW.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/pr2_catalog_load_eval.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/pr3_repo_native_plateau.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/pr4_transform_kinds.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/pr5_extraction_recall_taxonomy.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/sprint_08_changelogs_fullindex.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/measurements/sprint_08_fullcorpus_index.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/gain_1.29.0_05c6943.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/gain_1.30.0_2c8ac25.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/gain_1.30.1_26271fc.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/gain_1.31.0_a40c837.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/gain_1.32.0_c1bec3c.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/schema_comparison_with_schema.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/schema_comparison_without_schema.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/sprint_08_changelogs_fullindex.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/sprint_08_fullcorpus_index.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/metrics/sprint_pool_300s_plan.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/column_coverage_diagnostic.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/column_coverage_findings.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/dwh_graph_analysis.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/dwh_positional_insert_column_blindspot.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/feature_acceptance_dwh.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/graph_health_sprint_postmortem.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/island_lever_live_verification.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/issue38_pr2_live_acceptance.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/issue38_pr3_live_acceptance.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/lineage_identity_sprint_postmortem.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/pr_impact_followups_2026-06-14.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/sprint_03_v0.3.1_postmortem.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/sprint_3.1_postmortem.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/reports/v1_14_dialect_query_config_postmortem.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/blueprint.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/coverage_parse_failure_diagnosis.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/investigation_e5_e4.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/observed_usage_overlay_query_history_tableau.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/parse_diagnostics.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/parsing_errors_experiment.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/snowflake_en_test_suite.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/sql_only_coverage_lever_post_pr2.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/research/sqlcg.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/bundle_claude_skill.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/ci_tests_pool_flake_fix.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/column_lineage_recall_metric.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/coverage_p1_p3_p4.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/coverage_p1_p5_metric.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/coverage_parse_failures.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/diff-impact-producer-file.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/e8_dual_emission.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/feature_34_unused_presentation_segregation.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/feature_35_external_downstream_injection.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/feature_F2_bundle_claude_skill.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/feature_kuzu_to_duckdb_migration.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_backward_self_heal_index_at_sha.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_downstream_sink_location.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_dynamic_table_parsing.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_expand_qualify_perf.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_firstuser_findings.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_issue29_live_test_followups.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/fix_schema_case_mismatch.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/gain_coverage_metrics.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/graph_health_catalog_and_metrics.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/hygiene_config_path_and_survivors.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/issue-38-backfill-cte-bridge.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/issue-38-residual-source-extraction.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/issue-38-selects-from-island-lever.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/living_codebase_resync.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/mcp_server_self_healing.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/positional_insert_clone_blindspot.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_01.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_01_deployment_pypi.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_02.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_02_v0.3.0_core.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_03.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_04_column_lineage.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_04_column_lineage_fix.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_05_star_resolution.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_06_lineage_coverage.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_07_open_ecodes.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_07_perf_and_live_test.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_08_perf_upsert.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_09_lineage_coverage.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_10_anchor_tools.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_11_v1.0.2_bugfix.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_12_v1.1.0.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_13_v1.1.0_cluster_b.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_lineage_identity_and_session_context.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/sprint_postmortem_fixes.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/temp_table_namespacing.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/trust_layer.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/unfilled_table_impact.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1.1.0_cluster_b_provenance_trust.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1.1.0_live_graph_freshness.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1.1.1_batch_upsert_perf.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1.14.0_dialect_and_query_config_fixes.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1_1_2_bugfix.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1_1_3_union_cte_star.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1_2_0_read_proxy.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/v1_2_1_bugfix.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/plan/sprints/version-parity-and-restart.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/profile.html +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/pyrightconfig.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/scripts/collect_parse_errors.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/scripts/column_coverage_check.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/scripts/generate_cli_docs.sh +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/__main__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/analyze.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/catalog.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/db.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/find.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/gain.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/git.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/index.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/install.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/mcp.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/reindex.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/report.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/uninstall.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/commands/watch.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/coverage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/cli/main.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/config.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/freshness.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/jobs.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/noise_match.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/queries.cypher +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/core/schema.cypher +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/dbt_adapter.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/error_classify.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/git_delta.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/pool.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/walker.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/indexer/watcher.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/lineage/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/lineage/aggregator.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/lineage/schema_resolver.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/metrics/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/metrics/store.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/bigquery_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/postgres_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/registry.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/snowflake_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/parsers/tsql_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/control.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/exceptions.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/models.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/noise_filter.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/read_client.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/selfheal.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/server.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/skill.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/server/writer.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/utils/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/utils/hashing.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/utils/ignore.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/src/sqlcg/utils/logging.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/adversarial/200_join.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/adversarial/500_union.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/bench_indexer.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/conftest.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/tpch/q01.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/tpch/q02.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/tpch/q03.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/tpch/q04.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/benchmarks/tpch/q05.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/conftest.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/conftest.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_F2_skill_install_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_airbnb_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_cli_index.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_empty_impact_cli_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_git_hook_install.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_golden_lineage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_mcp_lifecycle.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_mcp_tools.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_pr_impact_cli_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_selfheal_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_star_resolution_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/e2e/test_watch.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/raw_listings.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/src_hosts.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/src_listings.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/airbnb/src_reviews.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/bigquery/.gitkeep +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/duckdb_parity/kuzu_reference.json +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/jaffle_shop/customers.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/jaffle_shop/orders.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/snowflake/base_tables.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/snowflake/reports.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/snowflake/views.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/star_corpus/etl_star.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/synthetic/base_tables.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/synthetic/reports.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/fixtures/synthetic/views.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/snowflake/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/snowflake/test_insert_select.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/snowflake/test_qualify_bare_tables_command_guard_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_T34_presentation_segregation.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_analyze_case_fold.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_anchor_tools.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_backfill_impact_consistency.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_bare_column_cte_lineage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_bulk_upsert.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_case_split_seed_regression.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_catalog_kind_upgrade.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_catalog_load_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cli_index_clear_before_rebuild.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_column_coverage_patterns.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_column_lineage_e2e.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_coverage_metrics_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cross_file_lineage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cte_key_namespacing_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cte_recall_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cte_schema_alias_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_cte_source_node_invariant.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_dialect_auto_resolution.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_dialect_matrix.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_duckdb_parity.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_e36_xfile_regression_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_empty_impact_blast_radius.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_empty_index_rollback_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_freshness_mcp.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_gating_join_retrofit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_hygiene_config_root_reconciliation.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_identity_counters_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_index_degraded_files_metric.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_index_filter_node_exclusion.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_indexer_batching.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_indexer_commits.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_indexer_to_graph.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_issue38_cte_insert_regression.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_key_normalization_chokepoint.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_live_anchors.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_mvcc_rebuild.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_pr1_confidence_reason.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_pr3_kind_tagging.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_read_via_server.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_readonly_under_lock.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_reindex_via_server.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_repo_relative_cte_namespaces.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_resolvable_write_col_edges_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_resync.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_selects_from_completeness.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_selects_from_cte_body_source.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_selects_from_subscope_source.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_single_writer_queue.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_star_resolution.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_temp_table_lineage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_temp_table_namespacing.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_union_cte_star_recall_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_usage_derived_catalog.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_use_schema_session_context_integration.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_user_surface_recall_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_v141_surface_guards.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_v1_14_0_dialect_and_query_config_fixes.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_view_kind_in_graph.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_write_memory_ceiling.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/perf/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/perf/test_perf.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E10/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E11/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E12/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E12/e12_json_path.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E12/test_e12.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E13/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E14/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E15/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E16/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E16/e16_merge.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E16/test_e16.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E17/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E18/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E18/e18_decode.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E18/e18_nvl2.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E18/test_e18.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E19/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E2/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E2/e2_function_alias.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E2/test_e2.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E20/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E21/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E21/test_e21.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E22/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E23/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E23/test_e23.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E24/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E25/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E25/e25_cross_db.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E25/e25_two_part.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E25/test_e25.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E25/test_e25_full_id.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E26/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E27/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E27/e27_udf.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E27/test_e27.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E28/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E29/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E3/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E3/e3_alter_table.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E3/test_e3.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E30/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E31/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E32/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E33/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E34/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E35/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E36/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E36/e36_temp_table.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E36/test_e36.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E36/test_e36_xfile.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E37/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E38/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/e4_unpivot.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E4/test_e4.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/test_e5.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E8/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E8/e8_uuid.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E8/test_e8.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E9/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_aggregates/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/README.md +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/fixture_etl.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/fixture_source.sql +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/conftest.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/snowflake/test_plan_review_gates.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/snowflake/__init__.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/snowflake/test_qualify_bare_tables_command_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/snowflake/test_scripting_noise.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_BugB_escalation_uses_init_path.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_BugC_hook_upgrade.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_F2_install_skill.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_F2_skill_render.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_F2_uninstall_skill.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_T09_01_qualify_once.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_T09_02_ddl_skip.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_T09_06_log_verbosity.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_T35_config_external_consumers.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_aggregator.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_aggregator_skip.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_analyze_case_fold.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_base_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_branch_monitor.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_bulk_upsert_invariant.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_canonical_target_resolution.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_catalog_csv_parsing.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_catalog_missing_warning.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_cli.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_cli_doc_flag_staleness.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_cli_help.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_clone_positional_insert_blindspot.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_closure_depth.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_column_lineage_wiring.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_config.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_coverage_metrics.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_cte_key_namespacing.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_cte_source_gap_metric.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_data_models.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_db_info.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_db_info_coverage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_db_path_isolation_fixture.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_doc_links.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_doc_markdown_link_existence.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_dominant_cause.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_duckdb_backend.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_duckdb_backend_shared.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_e5_view_alias_resolution.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_e8_dual_emission.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_e8_temp_chain_key_mismatch.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_empty_propagation_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_extract_select_output_columns.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_file_ignore_defaults.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_find_cmd.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_firstuser_findings.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_freshness_helper.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_gain_coverage.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_gain_ratio.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_gating_join_field_docstrings.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_git_delta.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_git_hooks.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_git_hooks_notify.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_graph_backend.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_graph_completeness_invariant.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_hard_kill_pool.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_has_column_precedence_upsert.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_hook_reindex_detach.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_hygiene_config_warning.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_identity_counters.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_include_working_tree.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_index_cmd.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_index_filter_config.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_index_flags.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_index_progress.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_index_summary_degraded_metric.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_indexer_progress.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_indexer_quality.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_install.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_install_message.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_issue_63_readonly_lock.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_jobs.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_judgement.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_lineage_conversion.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_literal_column_skip.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_mcp_best_practices.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_mcp_control.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_mcp_stdio_smoke.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_metrics.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_noise_filter.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_normalize_keys.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_parse_failed_classification.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_parse_file_dependency_filter.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_parse_quality.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_parser.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_perf_scaling_guard.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_pr07_observability.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_pr6_execute_immediate_unwrap.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_pr_impact_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_qualify_failed_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_queries_loader.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_read_client.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_repo_relative_cte_namespaces.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_resolvable_write_col_edges_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_schema_resolver.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_selects_from_completeness_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_selfheal_detector.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_selfheal_pr1_messages.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_selfheal_reexec.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_selfheal_watcher.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_server.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_skip_counts_persistence.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_sprint_06_t04_t05.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_star_resolution_unit.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_submit_feedback.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_subprocess_isolate.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_t02_expression_name_extraction.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_t03_ddl_skip.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_temp_table_namespacing.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_timeout_cancel.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_tool_version_stamp.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_tools_hints.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_tools_warnings.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_transform_kind_classification.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_uninstall.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_unknown_sentinel_skip.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_unqualified_fallback.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_upsert_batch_invariant.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_use_schema_session_context.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_version_parity.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_view_classification.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_walker.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_watcher.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_worker_error_classification.py +0 -0
- {sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/unit/test_writer_queue.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sql-code-graph
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.34.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
|
|
@@ -203,6 +203,14 @@ _EDGE_DDLS = [
|
|
|
203
203
|
PRIMARY KEY (src_key, dst_key)
|
|
204
204
|
)
|
|
205
205
|
""",
|
|
206
|
+
"""
|
|
207
|
+
CREATE TABLE IF NOT EXISTS "JOIN_COL_RESOLVE" (
|
|
208
|
+
src_key VARCHAR NOT NULL,
|
|
209
|
+
dst_key VARCHAR NOT NULL,
|
|
210
|
+
bare_col VARCHAR,
|
|
211
|
+
PRIMARY KEY (src_key, dst_key)
|
|
212
|
+
)
|
|
213
|
+
""",
|
|
206
214
|
]
|
|
207
215
|
|
|
208
216
|
_INDEX_DDLS = [
|
|
@@ -230,6 +238,8 @@ _INDEX_DDLS = [
|
|
|
230
238
|
'CREATE INDEX IF NOT EXISTS idx_STAR_SOURCE_dst ON "STAR_SOURCE" (dst_key)',
|
|
231
239
|
'CREATE INDEX IF NOT EXISTS idx_CONSUMED_BY_src ON "CONSUMED_BY" (src_key)',
|
|
232
240
|
'CREATE INDEX IF NOT EXISTS idx_CONSUMED_BY_dst ON "CONSUMED_BY" (dst_key)',
|
|
241
|
+
'CREATE INDEX IF NOT EXISTS idx_JOIN_COL_RESOLVE_src ON "JOIN_COL_RESOLVE" (src_key)',
|
|
242
|
+
'CREATE INDEX IF NOT EXISTS idx_JOIN_COL_RESOLVE_dst ON "JOIN_COL_RESOLVE" (dst_key)',
|
|
233
243
|
]
|
|
234
244
|
|
|
235
245
|
# Node label → column list (all columns of that table, in order)
|
|
@@ -304,6 +314,7 @@ _EDGE_EXTRA_COLUMNS: dict[str, list[str]] = {
|
|
|
304
314
|
RelType.DECLARES: [],
|
|
305
315
|
RelType.STAR_SOURCE: ["qualifier", "target_table", "confidence"],
|
|
306
316
|
RelType.CONSUMED_BY: [],
|
|
317
|
+
RelType.JOIN_COL_RESOLVE: ["bare_col"],
|
|
307
318
|
}
|
|
308
319
|
|
|
309
320
|
|
|
@@ -752,6 +763,7 @@ class DuckDBBackend(GraphBackend):
|
|
|
752
763
|
"UPDATES",
|
|
753
764
|
"DECLARES",
|
|
754
765
|
"STAR_SOURCE",
|
|
766
|
+
"JOIN_COL_RESOLVE",
|
|
755
767
|
):
|
|
756
768
|
self._conn.execute(
|
|
757
769
|
f'DELETE FROM "{edge_table}" WHERE src_key IN ({placeholders})',
|
|
@@ -891,6 +903,39 @@ class DuckDBBackend(GraphBackend):
|
|
|
891
903
|
row = result.fetchone()
|
|
892
904
|
return int(row[0]) if row else 0
|
|
893
905
|
|
|
906
|
+
def resolve_join_columns(self) -> int:
|
|
907
|
+
"""Resolve JOIN_COL_RESOLVE markers into concrete COLUMN_LINEAGE edges.
|
|
908
|
+
|
|
909
|
+
Runs AFTER ingestion AND after the catalog has been applied, so that
|
|
910
|
+
information_schema ``HAS_COLUMN`` rows are present. For each parse-time
|
|
911
|
+
marker (a bare unqualified column in a >=2-table join projection), it
|
|
912
|
+
finds which of the query's source tables owns a column with that bare
|
|
913
|
+
name (any HAS_COLUMN source), normalising casing on both sides:
|
|
914
|
+
|
|
915
|
+
- exactly one owner -> one high-confidence (0.9) edge (the dominant
|
|
916
|
+
live case: the second table is visible only via information_schema);
|
|
917
|
+
- more than one owner -> one low-confidence (0.5) edge per owner
|
|
918
|
+
(genuine ambiguity; over-attribute, never silently mis-pick);
|
|
919
|
+
- zero owners -> emit nothing (honest empty; XML-DDL gap).
|
|
920
|
+
|
|
921
|
+
Mirrors :meth:`expand_star_sources` (post-index SQL pass). The
|
|
922
|
+
suppressed sqlglot mis-bind edge is never emitted at parse time, so this
|
|
923
|
+
pass is the SOLE producer of these columns' edges — it MUST run in every
|
|
924
|
+
path that re-creates the markers (full index + both incremental paths).
|
|
925
|
+
|
|
926
|
+
Returns:
|
|
927
|
+
Number of COLUMN_LINEAGE JOIN_COL_RESOLVED edges present afterward.
|
|
928
|
+
"""
|
|
929
|
+
from sqlcg.core.queries import RESOLVE_JOIN_COLUMNS_QUERY
|
|
930
|
+
|
|
931
|
+
self._conn.execute(RESOLVE_JOIN_COLUMNS_QUERY)
|
|
932
|
+
result = self._conn.execute(
|
|
933
|
+
'SELECT count(*) AS n FROM "COLUMN_LINEAGE" WHERE transform = ?',
|
|
934
|
+
["JOIN_COL_RESOLVED"],
|
|
935
|
+
)
|
|
936
|
+
row = result.fetchone()
|
|
937
|
+
return int(row[0]) if row else 0
|
|
938
|
+
|
|
894
939
|
# ------------------------------------------------------------------
|
|
895
940
|
# Full-rebuild helpers
|
|
896
941
|
# ------------------------------------------------------------------
|
|
@@ -927,6 +972,7 @@ class DuckDBBackend(GraphBackend):
|
|
|
927
972
|
"DECLARES",
|
|
928
973
|
"STAR_SOURCE",
|
|
929
974
|
"CONSUMED_BY",
|
|
975
|
+
"JOIN_COL_RESOLVE",
|
|
930
976
|
]
|
|
931
977
|
for tbl in edge_tables + node_tables:
|
|
932
978
|
self._conn.execute(f'DELETE FROM "{tbl}"')
|
|
@@ -273,6 +273,16 @@ class GraphBackend(ABC):
|
|
|
273
273
|
"""
|
|
274
274
|
raise NotImplementedError(f"{type(self).__name__} does not support expand_star_sources")
|
|
275
275
|
|
|
276
|
+
def resolve_join_columns(self) -> int:
|
|
277
|
+
"""Resolve JOIN_COL_RESOLVE markers into per-column COLUMN_LINEAGE edges.
|
|
278
|
+
|
|
279
|
+
Runs once per index after ingestion AND catalog apply, resolving bare
|
|
280
|
+
unqualified join columns against the full post-index HAS_COLUMN catalog
|
|
281
|
+
(including information_schema rows unavailable at parse time). Concrete
|
|
282
|
+
backends must override this; returns the total JOIN_COL_RESOLVED edge count.
|
|
283
|
+
"""
|
|
284
|
+
raise NotImplementedError(f"{type(self).__name__} does not support resolve_join_columns")
|
|
285
|
+
|
|
276
286
|
|
|
277
287
|
def indexed_repo_root(db: "GraphBackend") -> Path | None:
|
|
278
288
|
"""Return the indexed root path stored on the first Repo node, or None.
|
|
@@ -51,6 +51,8 @@ LIST_DIALECTS_AND_REPOS_QUERY = _Q["LIST_DIALECTS_AND_REPOS"]
|
|
|
51
51
|
EXPAND_STAR_SOURCES_QUERY = _Q["EXPAND_STAR_SOURCES"]
|
|
52
52
|
EXPAND_STAR_SOURCES_HAS_COLUMN_QUERY = _Q["EXPAND_STAR_SOURCES_HAS_COLUMN"]
|
|
53
53
|
EXPAND_STAR_SOURCES_LINEAGE_QUERY = _Q["EXPAND_STAR_SOURCES_LINEAGE"]
|
|
54
|
+
RESOLVE_JOIN_COLUMNS_QUERY = _Q["RESOLVE_JOIN_COLUMNS"]
|
|
55
|
+
COUNT_JOIN_COL_RESOLVED_QUERY = _Q["COUNT_JOIN_COL_RESOLVED"]
|
|
54
56
|
COUNT_STAR_SOURCES_QUERY = _Q["COUNT_STAR_SOURCES"]
|
|
55
57
|
COUNT_STAR_EXPANSIONS_QUERY = _Q["COUNT_STAR_EXPANSIONS"]
|
|
56
58
|
FIND_DEFINITION_QUERY = _Q["FIND_DEFINITION"]
|
|
@@ -148,6 +148,53 @@ JOIN "SqlTable" tgt ON tgt.qualified = q.target_table
|
|
|
148
148
|
WHERE q.target_table <> ''
|
|
149
149
|
AND q.target_table <> t.qualified
|
|
150
150
|
|
|
151
|
+
-- RESOLVE_JOIN_COLUMNS
|
|
152
|
+
-- Resolve JOIN_COL_RESOLVE markers (bare unqualified join columns whose owning
|
|
153
|
+
-- table was only knowable post-index, e.g. catalogued via information_schema)
|
|
154
|
+
-- into concrete COLUMN_LINEAGE edges.
|
|
155
|
+
--
|
|
156
|
+
-- For each marker (src_key=query_id, dst_key=<dst_table>.<dst_col>, bare_col):
|
|
157
|
+
-- find which of the query's SELECTS_FROM source tables OWNS a column named
|
|
158
|
+
-- bare_col (any HAS_COLUMN source: ddl | information_schema | star_expansion |
|
|
159
|
+
-- usage). Casing is normalised on BOTH sides of the owner-match join because
|
|
160
|
+
-- information_schema stores col_name as exported (e.g. STATUS) while the parsed
|
|
161
|
+
-- bare name is lowercased (status).
|
|
162
|
+
--
|
|
163
|
+
-- Confidence contract:
|
|
164
|
+
-- - exactly one owning table -> HIGH confidence (0.9), the resolved edge
|
|
165
|
+
-- - more than one owning table -> one LOW confidence (0.5) edge per owner
|
|
166
|
+
-- (genuine ambiguity: over-attribute, never silently mis-pick)
|
|
167
|
+
-- - zero owning tables -> emit nothing (honest empty; XML-DDL gap)
|
|
168
|
+
-- A window COUNT over the owning tables per marker selects the confidence in one
|
|
169
|
+
-- pass.
|
|
170
|
+
-- params: []
|
|
171
|
+
INSERT OR REPLACE INTO "COLUMN_LINEAGE"
|
|
172
|
+
(src_key, dst_key, transform, confidence, query_id, inferred_from_source_name)
|
|
173
|
+
SELECT
|
|
174
|
+
src_key,
|
|
175
|
+
dst_key,
|
|
176
|
+
'JOIN_COL_RESOLVED' AS transform,
|
|
177
|
+
CASE WHEN n_owners = 1 THEN 0.9 ELSE 0.5 END AS confidence,
|
|
178
|
+
query_id,
|
|
179
|
+
FALSE AS inferred_from_source_name
|
|
180
|
+
FROM (
|
|
181
|
+
SELECT
|
|
182
|
+
c.id AS src_key,
|
|
183
|
+
m.dst_key AS dst_key,
|
|
184
|
+
m.src_key AS query_id,
|
|
185
|
+
count(*) OVER (PARTITION BY m.src_key, m.dst_key) AS n_owners
|
|
186
|
+
FROM "JOIN_COL_RESOLVE" m
|
|
187
|
+
JOIN "SELECTS_FROM" sf ON sf.src_key = m.src_key
|
|
188
|
+
JOIN "HAS_COLUMN" hc ON hc.src_key = sf.dst_key
|
|
189
|
+
JOIN "SqlColumn" c
|
|
190
|
+
ON c.id = hc.dst_key
|
|
191
|
+
AND lower(c.col_name) = lower(m.bare_col)
|
|
192
|
+
) owners
|
|
193
|
+
|
|
194
|
+
-- COUNT_JOIN_COL_RESOLVED
|
|
195
|
+
-- params: []
|
|
196
|
+
SELECT count(*) AS n FROM "COLUMN_LINEAGE" WHERE transform = 'JOIN_COL_RESOLVED'
|
|
197
|
+
|
|
151
198
|
-- COUNT_STAR_SOURCES
|
|
152
199
|
-- params: []
|
|
153
200
|
SELECT count(*) AS n FROM "STAR_SOURCE"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from enum import StrEnum
|
|
4
4
|
from importlib.resources import files
|
|
5
5
|
|
|
6
|
-
SCHEMA_VERSION = "
|
|
6
|
+
SCHEMA_VERSION = "11"
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class NodeLabel(StrEnum):
|
|
@@ -29,6 +29,7 @@ class RelType(StrEnum):
|
|
|
29
29
|
DECLARES = "DECLARES"
|
|
30
30
|
STAR_SOURCE = "STAR_SOURCE"
|
|
31
31
|
CONSUMED_BY = "CONSUMED_BY"
|
|
32
|
+
JOIN_COL_RESOLVE = "JOIN_COL_RESOLVE"
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
# Backward-compatible aliases
|
|
@@ -47,6 +47,7 @@ class FileRowSet:
|
|
|
47
47
|
selects_from_edges: list[dict] = field(default_factory=list)
|
|
48
48
|
column_lineage_edges: list[dict] = field(default_factory=list)
|
|
49
49
|
star_source_edges: list[dict] = field(default_factory=list)
|
|
50
|
+
join_col_resolve_edges: list[dict] = field(default_factory=list)
|
|
50
51
|
counts: dict = field(
|
|
51
52
|
default_factory=lambda: {"tables": 0, "edges": 0, "columns_defined": 0, "star_sources": 0}
|
|
52
53
|
)
|
|
@@ -71,6 +72,7 @@ class BatchRowBuffer:
|
|
|
71
72
|
selects_from_edges: list[dict] = field(default_factory=list)
|
|
72
73
|
column_lineage_edges: list[dict] = field(default_factory=list)
|
|
73
74
|
star_source_edges: list[dict] = field(default_factory=list)
|
|
75
|
+
join_col_resolve_edges: list[dict] = field(default_factory=list)
|
|
74
76
|
|
|
75
77
|
def extend(self, rows: FileRowSet) -> None:
|
|
76
78
|
"""Accumulate one file's row sets into this buffer."""
|
|
@@ -84,6 +86,7 @@ class BatchRowBuffer:
|
|
|
84
86
|
self.selects_from_edges.extend(rows.selects_from_edges)
|
|
85
87
|
self.column_lineage_edges.extend(rows.column_lineage_edges)
|
|
86
88
|
self.star_source_edges.extend(rows.star_source_edges)
|
|
89
|
+
self.join_col_resolve_edges.extend(rows.join_col_resolve_edges)
|
|
87
90
|
|
|
88
91
|
@classmethod
|
|
89
92
|
def from_single(cls, rows: FileRowSet) -> "BatchRowBuffer":
|
|
@@ -292,6 +295,9 @@ def _flush_row_batch(
|
|
|
292
295
|
star_source_edges = list(
|
|
293
296
|
{(r["src_key"], r["dst_key"]): r for r in buf.star_source_edges}.values()
|
|
294
297
|
)
|
|
298
|
+
join_col_resolve_edges = list(
|
|
299
|
+
{(r["src_key"], r["dst_key"]): r for r in buf.join_col_resolve_edges}.values()
|
|
300
|
+
)
|
|
295
301
|
|
|
296
302
|
# --- Phase B2: usage-derived catalog harvest ---
|
|
297
303
|
# Post-dedup: for each COLUMN_LINEAGE src endpoint whose table is a physical
|
|
@@ -345,6 +351,11 @@ def _flush_row_batch(
|
|
|
345
351
|
star_source_edges = [
|
|
346
352
|
r for r in star_source_edges if r["dst_key"] not in excluded_tables
|
|
347
353
|
]
|
|
354
|
+
join_col_resolve_edges = [
|
|
355
|
+
r
|
|
356
|
+
for r in join_col_resolve_edges
|
|
357
|
+
if _table_of_column_id(r["dst_key"]) not in excluded_tables
|
|
358
|
+
]
|
|
348
359
|
column_lineage_edges = [
|
|
349
360
|
r
|
|
350
361
|
for r in column_lineage_edges
|
|
@@ -372,6 +383,9 @@ def _flush_row_batch(
|
|
|
372
383
|
NodeLabel.COLUMN, NodeLabel.COLUMN, RelType.COLUMN_LINEAGE, column_lineage_edges
|
|
373
384
|
)
|
|
374
385
|
db.upsert_edges_bulk(NodeLabel.QUERY, NodeLabel.TABLE, RelType.STAR_SOURCE, star_source_edges)
|
|
386
|
+
db.upsert_edges_bulk(
|
|
387
|
+
NodeLabel.QUERY, NodeLabel.COLUMN, RelType.JOIN_COL_RESOLVE, join_col_resolve_edges
|
|
388
|
+
)
|
|
375
389
|
|
|
376
390
|
|
|
377
391
|
def _subprocess_parse_worker(parser_cls, dialect, path, sql, q):
|
|
@@ -882,6 +896,12 @@ class Indexer:
|
|
|
882
896
|
if profile:
|
|
883
897
|
_t_catalog_end = time.perf_counter()
|
|
884
898
|
|
|
899
|
+
# Post-catalog: resolve JOIN_COL_RESOLVE markers against the full HAS_COLUMN
|
|
900
|
+
# catalog (Bug #5, PR-5 option b). MUST run after the catalog is applied so
|
|
901
|
+
# information_schema columns are present; the suppressed sqlglot mis-bind
|
|
902
|
+
# edge is never emitted, so this is the sole producer of the resolved edges.
|
|
903
|
+
join_cols_resolved = self._resolve_join_columns(db)
|
|
904
|
+
|
|
885
905
|
# Classify all errors into buckets for measurement and reporting
|
|
886
906
|
error_summary: dict[str, int] = {
|
|
887
907
|
"E1": 0,
|
|
@@ -931,6 +951,7 @@ class Indexer:
|
|
|
931
951
|
"columns_defined": nonlocal_counts["columns_defined"],
|
|
932
952
|
"star_sources": nonlocal_counts["star_sources"],
|
|
933
953
|
"star_edges_expanded": star_edges_expanded,
|
|
954
|
+
"join_cols_resolved": join_cols_resolved,
|
|
934
955
|
"quality": nonlocal_counts["quality"],
|
|
935
956
|
"error_summary": error_summary,
|
|
936
957
|
"degraded_files": degraded_files,
|
|
@@ -1329,6 +1350,14 @@ class Indexer:
|
|
|
1329
1350
|
# ---- Step 8: Single star expansion (same as index_repo) ------------------
|
|
1330
1351
|
self._expand_star_sources(db)
|
|
1331
1352
|
|
|
1353
|
+
# ---- Step 8b: Resolve JOIN_COL_RESOLVE markers (Bug #5, PR-5 option b) ----
|
|
1354
|
+
# The incremental path does NOT reapply the catalog — it resolves against the
|
|
1355
|
+
# information_schema HAS_COLUMN rows persisted by the prior full index. Without
|
|
1356
|
+
# this, a delta touching a join file would re-create the markers but never
|
|
1357
|
+
# resolve them, silently dropping the join-column edges until the next full
|
|
1358
|
+
# index (plan-review BLOCKER).
|
|
1359
|
+
self._resolve_join_columns(db)
|
|
1360
|
+
|
|
1332
1361
|
# ---- Step 9: Persist new SHA on success ----------------------------------
|
|
1333
1362
|
db.set_indexed_sha(new_sha)
|
|
1334
1363
|
|
|
@@ -1382,6 +1411,13 @@ class Indexer:
|
|
|
1382
1411
|
# Re-run star expansion after re-indexing
|
|
1383
1412
|
self._expand_star_sources(db)
|
|
1384
1413
|
|
|
1414
|
+
# Resolve JOIN_COL_RESOLVE markers (Bug #5, PR-5 option b) against the
|
|
1415
|
+
# information_schema HAS_COLUMN rows persisted by the prior full index. The
|
|
1416
|
+
# single-file path does NOT reapply the catalog; without re-resolving here a
|
|
1417
|
+
# reindex of a join file would re-create the markers but drop the resolved
|
|
1418
|
+
# join-column edges until the next full index (plan-review BLOCKER).
|
|
1419
|
+
self._resolve_join_columns(db)
|
|
1420
|
+
|
|
1385
1421
|
def _index_single_file(self, parser, path: Path, sql: str, timeout: int) -> ParsedFile:
|
|
1386
1422
|
"""Parse one file, with optional timeout via subprocess isolation.
|
|
1387
1423
|
|
|
@@ -1706,6 +1742,21 @@ class Indexer:
|
|
|
1706
1742
|
)
|
|
1707
1743
|
rows.counts["star_sources"] += 1
|
|
1708
1744
|
|
|
1745
|
+
# JOIN_COL_RESOLVE markers (Bug #5, PR-5 option b): bare unqualified
|
|
1746
|
+
# join-projection columns whose owning source table is only knowable
|
|
1747
|
+
# post-index (e.g. catalogued via information_schema). The sqlglot
|
|
1748
|
+
# mis-bind edge was suppressed at parse time; the post-index resolver
|
|
1749
|
+
# (DuckDBBackend.resolve_join_columns) is the SOLE producer of these
|
|
1750
|
+
# columns' COLUMN_LINEAGE edges. src_key=query_id, dst_key=<dst>.<col>.
|
|
1751
|
+
for jcr in stmt.join_col_resolves:
|
|
1752
|
+
rows.join_col_resolve_edges.append(
|
|
1753
|
+
{
|
|
1754
|
+
"src_key": query_id,
|
|
1755
|
+
"dst_key": jcr.dst.full_id,
|
|
1756
|
+
"bare_col": jcr.bare_col,
|
|
1757
|
+
}
|
|
1758
|
+
)
|
|
1759
|
+
|
|
1709
1760
|
# Upsert target table node (if not already a defined_table)
|
|
1710
1761
|
# so that star expansion can create destination columns.
|
|
1711
1762
|
# #44: when a canonical_by_bare index is available, attempt to resolve
|
|
@@ -1930,6 +1981,22 @@ class Indexer:
|
|
|
1930
1981
|
"""
|
|
1931
1982
|
return db.expand_star_sources()
|
|
1932
1983
|
|
|
1984
|
+
def _resolve_join_columns(self, db: GraphBackend) -> int:
|
|
1985
|
+
"""Run the post-index join-column resolution (Bug #5, PR-5 option b).
|
|
1986
|
+
|
|
1987
|
+
Calls DuckDBBackend.resolve_join_columns(), which resolves JOIN_COL_RESOLVE
|
|
1988
|
+
markers (bare unqualified join columns) against the full post-index
|
|
1989
|
+
HAS_COLUMN catalog — including information_schema rows unavailable at parse
|
|
1990
|
+
time. MUST run AFTER the catalog is applied (full-index path) and AFTER star
|
|
1991
|
+
expansion in every path that re-creates the markers; the suppressed sqlglot
|
|
1992
|
+
mis-bind edge is never emitted, so this pass is the SOLE producer of these
|
|
1993
|
+
columns' edges.
|
|
1994
|
+
|
|
1995
|
+
Returns:
|
|
1996
|
+
Number of COLUMN_LINEAGE JOIN_COL_RESOLVED edges after resolution.
|
|
1997
|
+
"""
|
|
1998
|
+
return db.resolve_join_columns()
|
|
1999
|
+
|
|
1933
2000
|
def _ingest_external_consumers(self, db: GraphBackend, path: Path) -> dict:
|
|
1934
2001
|
"""Ingest declared external downstream consumers from .sqlcg.toml.
|
|
1935
2002
|
|
|
@@ -622,6 +622,7 @@ class AnsiParser(SqlParser):
|
|
|
622
622
|
)
|
|
623
623
|
column_lineage = extraction.edges
|
|
624
624
|
star_sources = extraction.star_sources
|
|
625
|
+
join_col_resolves = extraction.join_col_resolves
|
|
625
626
|
stmt_qualify_failed = extraction.qualify_failed
|
|
626
627
|
|
|
627
628
|
# Extract defined columns for CREATE TABLE statements
|
|
@@ -666,6 +667,7 @@ class AnsiParser(SqlParser):
|
|
|
666
667
|
parsing_mode="sqlglot",
|
|
667
668
|
defined_columns=defined_columns,
|
|
668
669
|
star_sources=star_sources,
|
|
670
|
+
join_col_resolves=join_col_resolves,
|
|
669
671
|
defined_body=defined_body,
|
|
670
672
|
clone_source=clone_source,
|
|
671
673
|
)
|
|
@@ -204,6 +204,32 @@ class StarSource:
|
|
|
204
204
|
qualifier: str | None = None
|
|
205
205
|
|
|
206
206
|
|
|
207
|
+
@dataclass(frozen=True)
|
|
208
|
+
class JoinColResolve:
|
|
209
|
+
"""A deferred-resolution marker for a bare unqualified join-projection column.
|
|
210
|
+
|
|
211
|
+
Emitted (instead of the sqlglot mis-bind edge) when a top-level INSERT/CREATE
|
|
212
|
+
SELECT projection contains a bare column (``exp.Column`` with no ``.table``)
|
|
213
|
+
AND the statement has >=2 source tables. The owning source table is only
|
|
214
|
+
knowable AFTER indexing (e.g. catalogued via information_schema), so the
|
|
215
|
+
binding is deferred to ``DuckDBBackend.resolve_join_columns`` — the post-index
|
|
216
|
+
pass is the SOLE producer of the resolved COLUMN_LINEAGE edge for this column.
|
|
217
|
+
|
|
218
|
+
Mirrors the over-attribution-instead-of-mis-bind discipline of the
|
|
219
|
+
``CTE_PROJECTION_AMBIGUOUS`` precedent (see PR-5 in
|
|
220
|
+
plan/sprints/bugfix_lineage_correctness_validation.md).
|
|
221
|
+
|
|
222
|
+
Attributes:
|
|
223
|
+
dst: The destination ColumnRef the projection would have produced
|
|
224
|
+
(``<dst_table>.<dst_col_name>``); its full_id is the marker's dst_key.
|
|
225
|
+
bare_col: The bare (unqualified) column name to resolve against source
|
|
226
|
+
tables' HAS_COLUMN catalog.
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
dst: ColumnRef
|
|
230
|
+
bare_col: str = ""
|
|
231
|
+
|
|
232
|
+
|
|
207
233
|
@dataclass(frozen=True)
|
|
208
234
|
class LineageExtraction:
|
|
209
235
|
"""Result of column lineage extraction, including both edges and star markers.
|
|
@@ -211,6 +237,8 @@ class LineageExtraction:
|
|
|
211
237
|
Attributes:
|
|
212
238
|
edges: List of LineageEdge objects extracted from the statement
|
|
213
239
|
star_sources: List of StarSource markers for SELECT * projections
|
|
240
|
+
join_col_resolves: List of JoinColResolve markers for bare unqualified
|
|
241
|
+
>=2-table join projections, resolved post-index against HAS_COLUMN.
|
|
214
242
|
qualify_failed: True when the qualify() step raised an exception for
|
|
215
243
|
this statement (schema-free retry may still yield a partial scope).
|
|
216
244
|
Propagated to QueryNode.qualify_failed for per-statement storage.
|
|
@@ -218,6 +246,7 @@ class LineageExtraction:
|
|
|
218
246
|
|
|
219
247
|
edges: list[LineageEdge]
|
|
220
248
|
star_sources: list[StarSource]
|
|
249
|
+
join_col_resolves: list[JoinColResolve] = field(default_factory=list)
|
|
221
250
|
qualify_failed: bool = False
|
|
222
251
|
|
|
223
252
|
|
|
@@ -268,6 +297,7 @@ class QueryNode:
|
|
|
268
297
|
confidence: float = 1.0
|
|
269
298
|
parsing_mode: str = "sqlglot"
|
|
270
299
|
star_sources: list[StarSource] = field(default_factory=list)
|
|
300
|
+
join_col_resolves: list[JoinColResolve] = field(default_factory=list)
|
|
271
301
|
defined_columns: list[str] = field(default_factory=list)
|
|
272
302
|
defined_body: Any | None = None
|
|
273
303
|
start_line: int = 0 # 1-based start line of statement in file; 0 = unknown
|
|
@@ -413,6 +443,22 @@ def normalize_keys(parsed: "ParsedFile", aliases: dict[str, str]) -> None:
|
|
|
413
443
|
if stmt.clone_source is not None:
|
|
414
444
|
stmt.clone_source = _norm_ref(stmt.clone_source)
|
|
415
445
|
|
|
446
|
+
# join_col_resolves (JoinColResolve.dst is a ColumnRef over a TableRef).
|
|
447
|
+
# The dst table is the INSERT/CREATE target, which is aliased above; keep
|
|
448
|
+
# the marker's dst_key in lockstep so the post-index resolver writes a
|
|
449
|
+
# COLUMN_LINEAGE edge with the same dst key as the rest of the graph.
|
|
450
|
+
new_join_col_resolves: list[JoinColResolve] = []
|
|
451
|
+
for jcr in stmt.join_col_resolves:
|
|
452
|
+
new_dst_table = _norm_ref(jcr.dst.table)
|
|
453
|
+
if new_dst_table is None:
|
|
454
|
+
# Empty-identity target — drop the marker (skip already logged).
|
|
455
|
+
continue
|
|
456
|
+
if new_dst_table is not jcr.dst.table:
|
|
457
|
+
new_dst = dataclasses.replace(jcr.dst, table=new_dst_table)
|
|
458
|
+
jcr = dataclasses.replace(jcr, dst=new_dst)
|
|
459
|
+
new_join_col_resolves.append(jcr)
|
|
460
|
+
stmt.join_col_resolves = new_join_col_resolves
|
|
461
|
+
|
|
416
462
|
# column_lineage — LineageEdge and ColumnRef are frozen; rewrite via replace
|
|
417
463
|
new_edges: list[LineageEdge] = []
|
|
418
464
|
for edge in stmt.column_lineage:
|
|
@@ -1067,6 +1113,7 @@ class SqlParser(ABC):
|
|
|
1067
1113
|
|
|
1068
1114
|
edges: list[LineageEdge] = []
|
|
1069
1115
|
star_sources: list[StarSource] = []
|
|
1116
|
+
join_col_resolves: list[JoinColResolve] = []
|
|
1070
1117
|
_qualify_failed: bool = False
|
|
1071
1118
|
|
|
1072
1119
|
# NEW (T-07-06): Record MERGE statements explicitly as deferred.
|
|
@@ -1417,6 +1464,23 @@ class SqlParser(ABC):
|
|
|
1417
1464
|
except Exception:
|
|
1418
1465
|
pass
|
|
1419
1466
|
|
|
1467
|
+
# Bug #5 (PR-5, option b): count distinct PHYSICAL source tables ONCE per
|
|
1468
|
+
# statement (never per column — CLAUDE.md hot-loop invariant). When a
|
|
1469
|
+
# top-level INSERT/CREATE-SELECT join has >=2 physical sources, bare
|
|
1470
|
+
# unqualified projection columns cannot be reliably bound at parse time
|
|
1471
|
+
# (the owning table may be catalogued only via information_schema, which
|
|
1472
|
+
# is unavailable to qualify()). For those columns we SUPPRESS the sqlglot
|
|
1473
|
+
# mis-bind edge and record a JoinColResolve marker instead — resolved
|
|
1474
|
+
# post-index against the full HAS_COLUMN catalog by
|
|
1475
|
+
# DuckDBBackend.resolve_join_columns(). This mirrors the
|
|
1476
|
+
# CTE_PROJECTION_AMBIGUOUS over-attribution discipline above, but defers
|
|
1477
|
+
# resolution rather than over-attributing immediately. No new
|
|
1478
|
+
# qualify/build_scope/exp.expand/sg_lineage call is added.
|
|
1479
|
+
_physical_source_count = sum(
|
|
1480
|
+
1 for _s in (query_sources or []) if getattr(_s, "role", "table") == "table"
|
|
1481
|
+
)
|
|
1482
|
+
_join_resolve_active = dst_table is not None and _physical_source_count >= 2
|
|
1483
|
+
|
|
1420
1484
|
# Extract output columns — skip positions handled by the positional INSERT block
|
|
1421
1485
|
for loop_idx, col_expr in enumerate(col_expressions):
|
|
1422
1486
|
if loop_idx in positional_col_names:
|
|
@@ -1490,6 +1554,26 @@ class SqlParser(ABC):
|
|
|
1490
1554
|
expr_type = type(col_expr).__name__
|
|
1491
1555
|
out.errors.append(f"col_lineage_skip:func_fallback:{expr_type}")
|
|
1492
1556
|
continue
|
|
1557
|
+
|
|
1558
|
+
# Bug #5 (PR-5, option b): bare unqualified column in a >=2-physical-
|
|
1559
|
+
# table join. SUPPRESS the sqlglot mis-bind edge (continue past
|
|
1560
|
+
# sg_lineage) and record a JoinColResolve marker; the post-index
|
|
1561
|
+
# resolver is the SOLE producer of this column's edge(s). A qualified
|
|
1562
|
+
# reference (o.amount) has c.table set and fails the bare test, so it
|
|
1563
|
+
# takes the existing sg_lineage path unchanged. This is the same
|
|
1564
|
+
# cardinality as the existing edge append — no new hot-loop op.
|
|
1565
|
+
if _join_resolve_active and dst_table is not None:
|
|
1566
|
+
_bare_cols = [c for c in col_expr.find_all(exp.Column) if not c.table]
|
|
1567
|
+
if _bare_cols:
|
|
1568
|
+
_bare_name = _bare_cols[0].name or col_name
|
|
1569
|
+
join_col_resolves.append(
|
|
1570
|
+
JoinColResolve(
|
|
1571
|
+
dst=ColumnRef(dst_table, col_name),
|
|
1572
|
+
bare_col=_bare_name,
|
|
1573
|
+
)
|
|
1574
|
+
)
|
|
1575
|
+
continue # skip sg_lineage for this projection
|
|
1576
|
+
|
|
1493
1577
|
# Schema validation: if schema is loaded and column isn't in it,
|
|
1494
1578
|
# emit a reduced-confidence edge rather than a full-confidence one.
|
|
1495
1579
|
# Skip when the expression has an explicit alias — the alias is the
|
|
@@ -1789,7 +1873,10 @@ class SqlParser(ABC):
|
|
|
1789
1873
|
out.errors.append(f"col_lineage:statement:{exc}")
|
|
1790
1874
|
|
|
1791
1875
|
return LineageExtraction(
|
|
1792
|
-
edges=edges,
|
|
1876
|
+
edges=edges,
|
|
1877
|
+
star_sources=star_sources,
|
|
1878
|
+
join_col_resolves=join_col_resolves,
|
|
1879
|
+
qualify_failed=_qualify_failed,
|
|
1793
1880
|
)
|
|
1794
1881
|
|
|
1795
1882
|
def _resolve_star_source(
|
|
@@ -2532,12 +2532,16 @@ def _diff_lost_producers(
|
|
|
2532
2532
|
lost_raw = before - after
|
|
2533
2533
|
new_raw = after - before
|
|
2534
2534
|
|
|
2535
|
-
#
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2535
|
+
# Lost-producer side: do NOT apply _exclude_synthetic_tables.
|
|
2536
|
+
# The lost set comes exclusively from GET_PRODUCER_TABLES (SqlQuery.target_table),
|
|
2537
|
+
# which is only ever a real top-level write target — a CTE/derived intermediate alias
|
|
2538
|
+
# is never a SqlQuery.target_table. An INSERT target with no surviving consumers
|
|
2539
|
+
# keeps kind='derived' (the indexer only upgrades 'derived'→'table' when a SELECT
|
|
2540
|
+
# reads the table elsewhere), so applying _exclude_synthetic_tables here would drop
|
|
2541
|
+
# genuine write targets that happen to be unconsumed (bug #3 false-safety signal).
|
|
2542
|
+
# The synthetic filter is still applied to the NEW-producer side below (for rename
|
|
2543
|
+
# classification), where genuine intermediate nodes can appear via new CTEs/views.
|
|
2544
|
+
lost_set = set(lost_raw)
|
|
2541
2545
|
|
|
2542
2546
|
if new_raw:
|
|
2543
2547
|
new_cleaned, _ = _exclude_synthetic_tables(db, sorted(new_raw))
|
{sql_code_graph-1.33.0 → sql_code_graph-1.34.0}/tests/integration/test_T35_external_consumers.py
RENAMED
|
@@ -129,8 +129,8 @@ def test_schema_version_matches_current_migration():
|
|
|
129
129
|
"""
|
|
130
130
|
from sqlcg.core.schema import SCHEMA_VERSION
|
|
131
131
|
|
|
132
|
-
assert SCHEMA_VERSION == "
|
|
133
|
-
f"SCHEMA_VERSION must be '
|
|
132
|
+
assert SCHEMA_VERSION == "11", (
|
|
133
|
+
f"SCHEMA_VERSION must be '11' after the JOIN_COL_RESOLVE edge-table addition; "
|
|
134
134
|
f"currently {SCHEMA_VERSION!r}"
|
|
135
135
|
)
|
|
136
136
|
|