By the time the analysis stage from 1.2 finishes, the SQL has become a Query tree. Catalog coordinates are baked in, locks (as we saw in 1.2.2) are already held from that point, and the type of every expression is determined. The starting point of this chapter is one fact: that Query tree does not go straight to the planner. There is one more stage in between, and that stage is the rewriter.
The rewriter's input and output are the same. It takes a Query tree and produces a Query tree. The number of trees that come out can be zero, one, or several. That means a single user SQL can fan out into multiple statements as it passes through the rewriter. The key point is that the input format and the output format are identical. The planner only receives Query trees that the rewriter passed through, and it does not distinguish whether a tree is exactly what the user wrote or the result of a transformation.
Why does this stage exist on its own? Analysis is the work of connecting the meaning of SQL to the catalog, and planning is the work of deciding how to execute that meaning. The transformation that sits between them, the one that does not change what the query means but does change the form of the query itself, is the rewriter's responsibility. Expanding a view reference into its underlying SELECT, injecting the WHERE condition of a row-level security (RLS) policy into the query, filling in defaults for columns omitted from an INSERT: all of this happens here.
1.3 splits into three sections.
- 1.3.1 Rule system and view expansion: the mechanism by which a view reference gets expanded in place into a sub-query. This expansion rides on the RULE system that PostgreSQL has carried since its early days, and we cover how that fact surfaces in application code.
- 1.3.2 How RLS rewrites queries: when a row-level security policy is defined in the catalog, how the rewriter weaves that policy into the query as a WHERE condition.
- 1.3.3 INSERT/UPDATE/DELETE rewriting: filling in default values, handling RETURNING, and the flow that turns an automatically updatable view into INSERT/UPDATE/DELETE against the view's base table.
By the end of this chapter, you should have a clear picture of where and how "the SQL I wrote" and "the SQL the planner saw" diverge. The three places they diverge are view expansion, RLS policy injection, and INSERT/UPDATE/DELETE rewriting. When EXPLAIN output or permission behavior does not match your intuition, recalling these three places is the start of an accurate trace.
Top comments (0)