Skip to content

Fixes #31790: upgrade collate-sqllineage to 2.1.7 for UPDATE and MERGE column lineage - #31885

Merged
IceS2 merged 4 commits into
mainfrom
upgrade-collate-sqllineage-dep
Aug 21, 2026
Merged

Fixes #31790: upgrade collate-sqllineage to 2.1.7 for UPDATE and MERGE column lineage#31885
IceS2 merged 4 commits into
mainfrom
upgrade-collate-sqllineage-dep

Conversation

@mohittilala

@mohittilala mohittilala commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Describe your changes:

Fixes #31790

I upgraded collate-sqllineage from 2.1.4 to 2.1.7 and removed the sqlparse override layer from the ingestion operator images, because 2.1.7 declares sqlparse==0.6.0 as a real dependency so the resolver now does the job the override was doing by hand.

That closes #31790. All four advisories (CVE-2026-54284, CVE-2026-59893, CVE-2026-71491, CVE-2026-59894) are fixed only in sqlparse 0.6.0, and 2.1.7 is the first collate-sqllineage release that both pins 0.6.0 and is co-installable with dbt-core. Of the three ceilings the issue lists, collate-sqllineage's own pin is lifted by this upgrade, and dbt-core's resolved upstream in 1.12.3 (sqlparse<0.7.0,>=0.5.5), which pip now selects on its own with no floor needed here.

The override is deleted rather than kept as belt-and-braces because it was pip install --no-deps plus a fail-closed import gate: it printed a resolver-conflict ERROR on every build and left pip check permanently unsatisfied. With the dependency declared properly none of that is needed, and leaving it in place would keep the noise for no benefit.

2.1.7 also fixes real lineage bugs. 2.1.4 produces no column lineage at all for UPDATE and MERGE. Table lineage still resolves, so the gap is quiet: the graph looks populated while every column edge on those statements is missing. Two regressions that shipped in 2.1.6 were found while validating this upgrade and are fixed in 2.1.7: SqlParse returned hash-order dependent column lineage for UPDATE, and SqlGlot leaked the UPDATE target alias into the graph as a phantom table. 2.1.7 additionally resolves JOIN and CTE aliases in UPDATE ... FROM, closing a case where SqlGlot returned empty column lineage while SqlFluff and SqlParse both resolved it correctly. That one lost lineage in production, since LineageParser takes the first parser that does not raise and SqlGlot was neither raising nor producing anything.

Type of change:

  • Bug fix

High-level design:

The tests are the substantive part of this PR.

They previously asserted [] for these statements, which documented the 2.1.4 limitation rather than the correct answer. They now assert the semantically correct and complete column lineage, with any parser that cannot produce it disabled and the reason recorded inline. Where no parser produces the correct lineage the test asserts it anyway and is marked xfail(strict=False), so it reports XPASS the moment upstream closes the gap rather than silently continuing to pass on a wrong expectation.

That direction was chosen over the alternative of asserting whatever the parsers currently emit. Several parser outputs here are wrong rather than merely incomplete (wildcard edges, a target column named after an aggregate expression), and freezing those into expectations would make the suite defend the bugs.

Tests:

Use cases covered

  • Column lineage for UPDATE ... FROM <cte>, resolved through the CTE to the base table
  • Column lineage for UPDATE ... FROM (subquery) JOIN ..., including the joined table source
  • Column lineage for UPDATE with correlated subqueries in SET
  • Column lineage for UPDATE whose SET expression reads the target's own alias
  • SET client_min_messages=notice and similar DDL, which correctly yields no lineage

Unit tests

  • I added unit tests for the new/changed logic.
  • Files updated:
    • ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py
    • ingestion/tests/unit/lineage/queries/test_specific_dialect_queries.py

Result against the published 2.1.7, stable across PYTHONHASHSEED 0/1/42/2024:

384 passed, 2 skipped, 2 xfailed, 0 failed

The 2.1.4 baseline was 386 passed, which reconciles as 384 passed plus the 2 xfailed.

Five tests that previously asserted [] now assert real lineage and pass:

test now asserts
test_update_with_join_and_cte price_history traced through the CTE
test_update_merge_01_update_with_join_and_column_mapping the chain latest_prices.new_price -> products.current_price -> products.price_change_percent, which exercises the alias fix
test_update_merge_02_update_with_cte sales traced through the CTE
test_update_merge_04_update_from_multiple_tables sales.quantity and the joined suppliers.lead_time_days
test_update_merge_08_update_with_correlated_subquery each reviews column to its own products column

Per-parser skips across these seven tests dropped from 17 to 7, and test_update_with_join_and_cte and test_update_merge_02_update_with_cte are now fully skip free: all three parsers enabled, cross-parser graph check enabled.

Two remain xfail(strict=False) with the correct lineage asserted, so they surface as XPASS once upstream closes them:

  • test_update_merge_06_update_with_window_functions: columns read through OVER (ORDER BY salary) produce no edge on any parser. Only AVG(salary), which reads it as a function argument, resolves.
  • test_update_merge_10_update_with_recursive_cte: SqlGlot traces the recursive CTE but over-reports, SqlFluff produces nothing, SqlParse stops at the CTE.

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (dependency bump, image cleanup, and unit test updates; no connector changes).

Playwright (UI) tests

  • Not applicable (no UI changes).

Manual testing performed

  1. Confirmed the published 2.1.7 declares sqlparse==0.6.0, requires_python>=3.10, so the image override is redundant.
  2. Confirmed both 2.1.6 regressions are gone using standalone repro scripts that exit non-zero when the bug is present. Both pass on 2.1.7 and fail on 2.1.6.
  3. Ran the lineage suite under 8 PYTHONHASHSEED values to confirm the non-determinism is gone. Failure counts on 2.1.6 varied run to run; on 2.1.7 they are identical every run.
  4. Verified through LineageParser end to end that UPDATE ... FROM <cte> now returns column edges instead of an empty result.

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added a test that covers the exact scenario we are fixing.

Greptile Summary

The PR upgrades collate-sqllineage and removes the ingestion-operator images’ manual sqlparse override. It also updates lineage expectations for UPDATE statements and adjusts parser participation where implementations still disagree.

  • Upgrades collate-sqllineage from 2.1.4 to 2.1.7.
  • Removes the explicit sqlparse installation and build-time parser gate from both operator Dockerfiles.
  • Adds concrete UPDATE column-lineage expectations and parser-specific exclusions.
  • Keeps the known unsupported assertions separate without whole-test xfail markers.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains from the previously reported issue.

No blocking failure remains.

Important Files Changed

Filename Overview
ingestion/setup.py Pins collate-sqllineage to 2.1.7.
ingestion/operators/docker/Dockerfile Removes the manual sqlparse override and its build-time validation gate.
ingestion/operators/docker/Dockerfile.ci Mirrors the production operator image cleanup in CI.
ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py Replaces empty UPDATE lineage expectations with concrete edges and no longer uses whole-test xfails that could mask unrelated regressions.
ingestion/tests/unit/lineage/queries/test_specific_dialect_queries.py Disables SqlGlot for unsupported PostgreSQL SET and ALTER SEQUENCE statements.

Reviews (3): Last reviewed commit: "Merge branch 'main' into upgrade-collate..." | Re-trigger Greptile

2.1.4 produces no column lineage for UPDATE and MERGE. Table lineage still
resolves, so the gap is quiet: the graph looks populated while every column
edge on those statements is missing. 2.1.7 also clears one of the
sqlparse>=0.6.0 ceilings tracked in the issue.

Update the lineage tests to assert the correct lineage instead of the empty
result that encoded the old limitation. Two shapes are still unresolved
upstream and stay marked xfail with the correct lineage asserted.
…r 4 CVEs (#31791)"

collate-sqllineage 2.1.7 carries sqlparse 0.6.0 in its own metadata, so the
resolver handles this without a --no-deps override and an import gate to keep
it honest.

Reverts 2e8f045.
Copilot AI lite review requested due to automatic review settings August 21, 2026 11:16
@mohittilala
mohittilala requested a review from a team as a code owner August 21, 2026 11:16
@mohittilala mohittilala self-assigned this Aug 21, 2026
@github-actions github-actions Bot added Ingestion safe to test Add this label to run secure Github workflows on PRs labels Aug 21, 2026
Comment thread ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the ingestion dependency collate-sqllineage to improve column-lineage extraction (notably for UPDATE/MERGE) and removes the now-redundant sqlparse override layer from the ingestion operator Docker images, updating unit tests to assert correct lineage outputs.

Changes:

  • Bump collate-sqllineage from 2.1.4 to 2.1.7 in ingestion/setup.py.
  • Remove the explicit sqlparse==0.6.0 override/install gate from ingestion operator image Dockerfiles.
  • Update/extend lineage unit tests (including xfail cases) to assert correct UPDATE/MERGE column lineage.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
ingestion/setup.py Upgrades collate-sqllineage pin to 2.1.7.
ingestion/operators/docker/Dockerfile Removes the sqlparse override layer from the operator runtime image build.
ingestion/operators/docker/Dockerfile.ci Removes the sqlparse override layer from the operator CI image build.
ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py Updates UPDATE/MERGE tests to assert correct column lineage; adds xfail coverage for known upstream gaps.
ingestion/tests/unit/lineage/queries/test_specific_dialect_queries.py Disables SqlGlot for Postgres DDL lineage tests where it raises on unsupported statements.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ingestion/setup.py
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit f2269ddbbe7efb5b82388fec30d53a89ed317132 in Playwright run 32487414440, attempt 1.

✅ 110 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 46m 11s

⏱️ Max setup 4m 38s · max shard execution 12m 54s · max shard-job elapsed before upload 17m 44s · reporting 4s

🌐 217.03 requests/attempt · 1.79 app boots/UI scenario · 0.00% common-shard skew

Optimization targets still in progress:

  • Browser traffic was 217.03 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 1.79 per UI scenario (216 boots / 121 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 46 0 0 0 0 0
✅ Shard ingestion-01 29 0 0 0 0 0
✅ Shard ingestion-02 35 0 0 0 0 0

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

…vention

Greptile flagged that whole-test xfails also cover the table-lineage and
parser checks, so an unrelated regression reports as XFAIL instead of
failing. Use the per-parser flags the rest of the file already uses.

merge_06 asserts the one edge all three parsers resolve, with a comment on
why the two window ORDER BY edges are missing. merge_10 goes back to an
empty expectation with SqlGlot and SqlParse disabled and their specific
errors named, plus skip_graph_check on the table assertion since SqlGlot
and SqlFluff build different internal shapes for the recursion.
Copilot AI review requested due to automatic review settings August 21, 2026 12:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (2)

ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py:6343

  • This block documents the semantically correct column lineage for the recursive CTE case (employees.employee_id -> reporting_chain/top_level_manager) but still asserts [] and disables SqlGlot for column lineage. With assert_column_lineage_equal’s exact set comparison, the test will fail if/when SqlGlot (or another parser) starts returning the correct edges (it will appear as “extra” lineage). Consider asserting the correct lineage and marking the current mismatch as an expected failure (xfail) limited to the column-lineage assertion, while keeping SqlGlot enabled so the test can start passing once the upstream behavior is fixed.
        assert_column_lineage_equal(
            query,
            [],
            dialect=Dialect.POSTGRES.value,
            # SqlGlot: traces to employees but adds manager_id as a source of the chain

ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py:6093

  • This test currently asserts only the single employees.salary -> employee_rankings.dept_avg_salary edge while explicitly documenting that salary_rank and salary_percentile have no lineage “yet”. Because assert_column_lineage_equal does an exact set comparison, the test will start failing as soon as any parser begins emitting those missing edges (an improvement). If the intent is to track an upstream gap without blocking the suite (as described in the PR), consider asserting the full expected lineage and marking the current mismatch as an expected failure (xfail) scoped just to the column-lineage assertion.

This issue also appears on line 6339 of the same file.

        assert_column_lineage_equal(
            query,
            [
                (
                    TestColumnQualifierTuple("salary", "employees"),

Copilot AI review requested due to automatic review settings August 21, 2026 13:32
@gitar-bot

gitar-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Upgrades collate-sqllineage to 2.1.7 and removes the manual sqlparse image override, resolving column lineage gaps for UPDATE and MERGE statements. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (2)

ingestion/setup.py:183

  • Bumping collate-sqllineage to 2.1.7 pulls in sqlparse==0.6.0, but the repo’s Airflow constraints still pin sqlparse==0.5.5 (see ingestion/airflow-constraints-3.3.0.txt:649). ingestion/Dockerfile.ci installs the ingestion package under that constraints file (pip install "." --constraint ...), so this dependency change will make that image build fail with an unsatisfiable constraint unless the constraints pin (or its usage) is updated.
    "requests>=2.32.4",
    "requests-aws4auth~=1.1",  # Only depends on requests as external package. Leaving as base.
    "sqlalchemy>=2.0.0,<3",
    "collate-sqllineage==2.1.7",
    "tabulate==0.9.0",
    "tenacity>=8.0,<10",

ingestion/tests/unit/lineage/queries/test_complex_query_patterns.py:6091

  • PR description says the window-function and recursive-CTE UPDATE cases are asserted with correct lineage and marked xfail(strict=False), but this test file contains no xfail markers and currently asserts only the partial lineage that the parsers emit (or []). If the intent is to surface XPASS when upstream fixes these, these tests need an explicit xfail + the correct expected lineage; otherwise the PR description should be updated to match the actual strategy.
        # All three window expressions read employees.salary through the "ranked" subquery.
        # Only AVG(salary) resolves, because it reads salary as a function argument. RANK()
        # and PERCENT_RANK() read it through OVER (ORDER BY salary), which no parser treats
        # as a source column, so salary_rank and salary_percentile have no edge yet.
        assert_column_lineage_equal(
            query,
            [

@sonarqubecloud

Copy link
Copy Markdown

@IceS2
IceS2 added this pull request to the merge queue Aug 21, 2026
Merged via the queue into main with commit f396940 Aug 21, 2026
107 checks passed
@IceS2
IceS2 deleted the upgrade-collate-sqllineage-dep branch August 21, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ingestion safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sqlparse pinned to a vulnerable version in ingestion images: 4 CVEs fixed only in 0.6.0

4 participants