Expand description
CTE scope tracking for SQL AST visitors.
Common Table Expressions (CTEs) introduce names that shadow database objects.
When traversing a SQL AST to collect dependencies, extract aliases, or
transform names, CTE references must be distinguished from real object
references. This module provides CteScope, a stack-based tracker that
manages CTE name visibility across nested queries.
§Scoping Rules
-
Simple CTEs (
WITH a AS (...), b AS (...) SELECT ...): names are introduced incrementally, left to right. Each simple CTE’s body sees only the CTEs declared before it; the name of CTEiis not in scope while visiting CTEi’s own body. All names are visible to the main query body. This mirrors Materialize’s name resolver (fold_queryinsrc/sql/src/names.rs,plan_ctesinsrc/sql/src/plan/query.rs), which resolves eachCteBlock::Simplebody before inserting that CTE’s name. As a result a simple CTE whose name shadows a catalog object can still reference that object inside its own definition, e.g.WITH products AS (SELECT * FROM products WHERE active) SELECT * FROM products— the innerproductsis the catalog table, the outer is the CTE. Callers drive this by pushing an empty scope, then visiting each body and callinginsert_currentafter each. -
Mutually Recursive CTEs (
WITH MUTUALLY RECURSIVE a AS (...), b AS (...) SELECT ...): All CTE names are visible to all CTE definitions and the main query body. Self-references and forward references are valid, so all names are pushed up front. -
Nested queries: Each subquery can introduce its own CTEs. The scope stack ensures inner CTE names shadow outer ones, and are properly removed when the subquery scope ends.
§Usage Pattern
Used with mz-sql-parser’s Visit / VisitMut traits by overriding
visit_query:
fn visit_query(&mut self, node: &'ast Query<Raw>) {
let names = CteScope::collect_cte_names(&node.ctes);
self.cte_scope.push(names);
visit::visit_query(self, node); // default traversal
self.cte_scope.pop();
}Then in visit_table_factor, check self.cte_scope.is_cte(name) before
treating a single-ident reference as a database object.
Structs§
- CteScope 🔒
- Stack-based tracker for CTE names currently in scope.