LINEAGE_ADJACENCY_LIST table
The LINEAGE_ADJACENCY_LIST table is a flat list of directed lineage edges between assets and processes. Each row represents a single hop, where from_guid is the upstream asset or process and to_guid is the downstream asset or process.
Use this table to traverse lineage starting from any asset. Pair it with the ASSETS table to resolve GUIDs to human-readable names and types.
Columns
The LINEAGE_ADJACENCY_LIST table includes the following columns:
| Column | Description |
|---|---|
from_guid | The GUID of the upstream asset or process in the edge |
to_guid | The GUID of the downstream asset or process in the edge |
Example queries
The examples below run on Snowflake. Recursive CTE syntax is similar across data warehouse engines, but the cycle-detection helpers (ARRAY_CONSTRUCT, ARRAY_APPEND, ARRAY_CONTAINS, ::VARIANT) are Snowflake-specific—adapt them to your engine's array functions if needed.
For multi-hop queries that return direction, hop level, and asset names in a single result set, see Set up lineage tables for the optional LINEAGE helper view.
Upstream lineage
Find every asset directly upstream of a target asset, joined to ASSETS for names and types.
- Direct
- With Cycle Detection
-- Replace '--' with the GUID of the asset you're tracing from.
SELECT guid, asset_name, asset_type
FROM (
WITH RECURSIVE lineage AS (
SELECT from_guid, 1 AS level
FROM gold.lineage_adjacency_list
WHERE to_guid = '--'
UNION ALL
SELECT a.from_guid, l.level + 1
FROM lineage l
JOIN gold.lineage_adjacency_list a
ON l.from_guid = a.to_guid
WHERE l.level < 50
)
SELECT DISTINCT from_guid FROM lineage
) t
LEFT JOIN gold.assets ON from_guid = guid;
For graphs that may contain cycles, track visited GUIDs and skip any edge that revisits one. The hop limit is raised to 100 since cycles are filtered out. The array functions (ARRAY_CONSTRUCT, ARRAY_APPEND, ARRAY_CONTAINS, ::VARIANT) are Snowflake-specific.
SELECT guid, asset_name, asset_type
FROM (
WITH RECURSIVE lineage AS (
SELECT from_guid, 1 AS level, ARRAY_CONSTRUCT(from_guid) AS visited
FROM gold.lineage_adjacency_list
WHERE to_guid = '--'
UNION ALL
SELECT a.from_guid, l.level + 1, ARRAY_APPEND(l.visited, a.from_guid)
FROM lineage l
JOIN gold.lineage_adjacency_list a
ON l.from_guid = a.to_guid
WHERE l.level < 100
AND NOT ARRAY_CONTAINS(a.from_guid::VARIANT, l.visited)
)
SELECT DISTINCT from_guid FROM lineage
) t
LEFT JOIN gold.assets ON from_guid = guid;
Downstream lineage
Find every asset directly downstream of a source asset.
- Direct
- With Cycle Detection
-- Replace '--' with the GUID of the asset you're tracing from.
SELECT guid, asset_name, asset_type
FROM (
WITH RECURSIVE lineage AS (
SELECT to_guid, 1 AS level
FROM gold.lineage_adjacency_list
WHERE from_guid = '--'
UNION ALL
SELECT a.to_guid, l.level + 1
FROM lineage l
JOIN gold.lineage_adjacency_list a
ON l.to_guid = a.from_guid
WHERE l.level < 50
)
SELECT DISTINCT to_guid FROM lineage
) t
LEFT JOIN gold.assets ON to_guid = guid;
Prevents infinite loops by tracking visited GUIDs. The array functions (ARRAY_CONSTRUCT, ARRAY_APPEND, ARRAY_CONTAINS, ::VARIANT) are Snowflake-specific.
SELECT guid, asset_name, asset_type
FROM (
WITH RECURSIVE lineage AS (
SELECT to_guid, 1 AS level, ARRAY_CONSTRUCT(to_guid) AS visited
FROM gold.lineage_adjacency_list
WHERE from_guid = '--'
UNION ALL
SELECT a.to_guid, l.level + 1, ARRAY_APPEND(l.visited, a.to_guid)
FROM lineage l
JOIN gold.lineage_adjacency_list a
ON l.to_guid = a.from_guid
WHERE l.level < 100
AND NOT ARRAY_CONTAINS(a.to_guid::VARIANT, l.visited)
)
SELECT DISTINCT to_guid FROM lineage
) t
LEFT JOIN gold.assets ON to_guid = guid;
Optional: Full-lineage stored procedure (Snowflake)
If you frequently explore lineage from a single starting asset, this Snowflake stored procedure walks both directions in one call. It returns edges (not just nodes) annotated with direction (upstream or downstream) and level (hop distance), and joins both ends to ASSETS for names and types.
The procedure walks up to 100 hops in each direction. Cycle suppression isn't built in—use the cycle-detection variants in the sections earlier if your graph contains cycles.
-- Replace:
-- <CONTEXT_STORE_DB> with your context store database
-- <CUSTOM_SCHEMA> with the schema where you want the procedure to live
CREATE OR REPLACE PROCEDURE <CONTEXT_STORE_DB>.<CUSTOM_SCHEMA>.FULL_LINEAGE(BASE_GUID VARCHAR)
RETURNS TABLE (
direction VARCHAR,
from_guid VARCHAR,
from_asset_name VARCHAR,
from_asset_type VARCHAR,
to_guid VARCHAR,
to_asset_name VARCHAR,
to_asset_type VARCHAR,
level INT
)
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
res RESULTSET DEFAULT (
WITH RECURSIVE upstream AS (
SELECT
from_guid,
to_guid,
1 AS level,
'upstream' AS direction
FROM <CONTEXT_STORE_DB>.GOLD.LINEAGE_ADJACENCY_LIST
WHERE to_guid = :BASE_GUID
UNION ALL
SELECT
a.from_guid,
a.to_guid,
l.level + 1,
'upstream'
FROM upstream l
JOIN <CONTEXT_STORE_DB>.GOLD.LINEAGE_ADJACENCY_LIST a
ON l.from_guid = a.to_guid
WHERE l.level < 100
),
downstream AS (
SELECT
from_guid,
to_guid,
1 AS level,
'downstream' AS direction
FROM <CONTEXT_STORE_DB>.GOLD.LINEAGE_ADJACENCY_LIST
WHERE from_guid = :BASE_GUID
UNION ALL
SELECT
a.from_guid,
a.to_guid,
l.level + 1,
'downstream'
FROM downstream l
JOIN <CONTEXT_STORE_DB>.GOLD.LINEAGE_ADJACENCY_LIST a
ON l.to_guid = a.from_guid
WHERE l.level < 100
),
combined AS (
SELECT
from_guid,
to_guid,
direction,
MIN(level) AS level
FROM (
SELECT * FROM upstream
UNION ALL
SELECT * FROM downstream
)
GROUP BY from_guid, to_guid, direction
)
SELECT
d.direction,
d.from_guid,
src.asset_name AS from_asset_name,
src.asset_type AS from_asset_type,
d.to_guid,
tgt.asset_name AS to_asset_name,
tgt.asset_type AS to_asset_type,
d.level
FROM combined d
LEFT JOIN <CONTEXT_STORE_DB>.GOLD.ASSETS src ON d.from_guid = src.guid
LEFT JOIN <CONTEXT_STORE_DB>.GOLD.ASSETS tgt ON d.to_guid = tgt.guid
ORDER BY d.direction, d.level
);
BEGIN
RETURN TABLE(res);
END;
$$;
Call it with the GUID of the asset you want to explore:
CALL <CONTEXT_STORE_DB>.<CUSTOM_SCHEMA>.FULL_LINEAGE('<base_guid>');
See also
- Gold namespace
- ASSETS table
- Set up lineage tables for optional helper views with direction and asset names
- Lineage use cases
- Atlan metamodel reference