feat(query): extract query lineage from plans#20201
Open
youngsofun wants to merge 1 commit into
Open
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
youngsofun
force-pushed
the
codex/extract-query-lineage
branch
from
July 24, 2026 22:50
0ad0d94 to
d3bc3c8
Compare
youngsofun
force-pushed
the
codex/extract-query-lineage
branch
from
July 24, 2026 23:47
d3bc3c8 to
5db6ae0
Compare
Contributor
🤖 CI Job Analysis (Retry 1)
📊 Summary
❌ NO RETRY NEEDEDAll failures appear to be code/test issues requiring manual fixes. 🔍 Job Details
🤖 AboutAutomated analysis using job annotations to distinguish infrastructure issues (auto-retried) from code/test issues (manual fixes needed). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I hereby agree to the terms of the CLA available at: https://docs.databend.com/dev/policies/cla/
Summary
Extract object-level and column-level lineage from optimized query plans and expose it through
Plan::query_lineage().This PR is the planner foundation for #20198. The larger lineage PR currently contains this same commit so its persistence and SQL tests remain executable end to end. This PR is intended to merge first; #20198 will then rebase onto
mainand drop the duplicate extraction commit.Motivation
Persistent lineage needs a canonical representation of which input relations and columns contribute data to each output relation and column. Deriving that information later from formatted SQL would duplicate binder semantics and would be unreliable for aliases, casts, subqueries, CTEs, optimizer rewrites, and mutation expressions.
This change keeps extraction in the planner, where resolved table identities, column IDs, scalar expressions, and the optimized relational tree are available. The output is storage-independent and can be consumed by metadata persistence separately.
Output model
QueryLineagerecords the statement kind and a set of canonical data-flow edges:The public extraction DTO groups upstream relations under each downstream relation. Column edges are sorted and deduplicated. Relations carry catalog, database, name, optional stable ID, and whether the relation is a table or view.
Supported target statements are:
CREATE TABLE ... AS SELECT(CTAS)CREATE VIEWINSERT ... SELECTREPLACE INTO ... SELECTUPDATE ... FROMandMERGEStatements without a data-producing query return no lineage.
Resolution algorithm
Extraction has two phases:
SExprand build symbol definitions for base scans and data-producing operators.Definitions are collected for scalar evaluation, aggregate functions, window functions, set-returning functions, UDFs, async functions,
UNION ALL, expression scans, and automatic materialized CTE references. Scalar subqueries are followed through their output symbols.Only target value expressions are roots of the traversal. Columns used exclusively by filters, join predicates,
WHENconditions, or ordering do not become lineage unless they also contribute to an output expression. Aggregate arguments such ascount(col)therefore propagatecol, whilecount(*)has no input column edge.Cycle detection prevents recursive symbol definitions from looping, and ordered sets make multi-source expressions deterministic.
Relation boundaries
AS MATERIALIZEDCTE lineage is not included yet because the query-scoped temporary relation does not retain the original producer-column mapping.Capture cost and execution semantics
The new
query.lineage.capture_enabledconfiguration defaults tofalse. Additional view-body planning, relation annotations, and target-ID capture are gated by this flag.For ordinary
INSERT, the target table ID is captured in a lineage-only field.table_inforemains unset, so execution continues to resolve the target by catalog/database/table name and does not become pinned to the table object seen during planning.This PR only extracts lineage. Metadata schema, persistence, lifecycle handling, and
GET_LINEAGEremain in #20198.Tests
Planner coverage includes CTAS, views, insert-select, view boundaries, CTEs, automatic materialized CTEs, joins and
EXISTSfilters,JOIN USING, replace, update, merge, and multi-table insert.Type of change
This change is