Skip to main content

rupg_analyze/
select.rs

1//! `transformSelectStmt` of `analyze.c`: `FROM`, the target list, the `WHERE` condition, `GROUP BY`, `HAVING`, `ORDER BY`, `DISTINCT`, `LIMIT` and `OFFSET`.
2
3use rupg_common::{Error, Result, SqlState};
4use rupg_sql::nodes::{LimitOption, List, Node, SelectStmt, SetOperation};
5use rupg_types::oid;
6
7use crate::Analyzer;
8use crate::agg::Kind;
9use crate::coerce::Context;
10use crate::colname::figure_colname;
11use crate::expr::{Expr, ExprKind};
12use crate::from::{FromItem, Relation};
13use crate::sort::SortGroup;
14use crate::window::WindowClause;
15
16/// The query tree of a `SELECT`.
17#[derive(Clone, Debug, Default, PartialEq)]
18pub struct Query {
19    /// The relations of `FROM`, which a [`crate::Var`] names by index.
20    pub relations: Vec<Relation>,
21    /// The parts of `FROM`. The query joins them with a cross join.
22    pub from: Vec<FromItem>,
23    /// The columns of the result, then the junk columns that only `ORDER BY` and `GROUP BY` read.
24    pub targets: Vec<Target>,
25    /// The `WHERE` condition, of type `boolean`.
26    pub filter: Option<Expr>,
27    /// True when the query makes groups of rows: it has an aggregate call, `GROUP BY` or `HAVING`. With no item of `GROUP BY`, all the rows make one group, also when there are no rows.
28    pub grouped: bool,
29    /// The items of `GROUP BY`.
30    pub group: Vec<SortGroup>,
31    /// `groupingSets`: the grouping sets of `GROUP BY`, or none for a plain `GROUP BY`. Each set makes groups on its own items, and the other items of `GROUP BY` are null in its rows.
32    pub grouping_sets: Vec<crate::GroupingSet>,
33    /// `groupDistinct`: `GROUP BY DISTINCT`, which makes the groups of the same grouping set once.
34    pub group_distinct: bool,
35    /// The `HAVING` condition, of type `boolean`, which each group must pass.
36    pub having: Option<Expr>,
37    /// The items of `ORDER BY`.
38    pub sort: Vec<SortGroup>,
39    /// The items of `DISTINCT` or `DISTINCT ON`. The items of `ORDER BY` come first.
40    pub distinct: Vec<SortGroup>,
41    /// True for `DISTINCT ON`, which keeps the first row of each group.
42    pub distinct_on: bool,
43    /// `OFFSET` as `bigint`.
44    pub offset: Option<Expr>,
45    /// `LIMIT` or `FETCH FIRST` as `bigint`.
46    pub limit: Option<Expr>,
47    /// `FETCH FIRST ... WITH TIES`: the rows equal to the last row on the items of `ORDER BY` come too.
48    pub with_ties: bool,
49    /// The type OID of each parameter, from `$1`.
50    pub params: Vec<u32>,
51    /// The warnings and notices of the analysis, which the session sends before the result.
52    pub notices: Vec<Error>,
53    /// `UNION`, `INTERSECT` or `EXCEPT`. Each `SELECT` of the operation is a subquery in [`Query::relations`], and the rows of the operation are the rows of the leftmost one, which the targets read. The query has no `FROM`.
54    pub set_op: Option<crate::SetOp>,
55    /// The windows of the window function calls and of the `WINDOW` clause. A [`crate::WindowFunc`] names its window by its number, from 1.
56    pub windows: Vec<WindowClause>,
57    /// `cteList`: the queries of the `WITH` clause of the query.
58    pub ctes: Vec<crate::Cte>,
59    /// `hasRecursive`: the query has `WITH RECURSIVE`.
60    pub recursive: bool,
61    /// `rowMarks`: the relations that `FOR UPDATE` or `FOR SHARE` locks.
62    pub row_marks: Vec<crate::RowMark>,
63    /// The table that an `INSERT` writes, or `None` for a `SELECT`.
64    pub write: Option<crate::Write>,
65    /// `outargs` of `CallStmt`: the arguments of `CALL` for the `INOUT` and `OUT` arguments of the procedure, in order.
66    pub out_args: Vec<crate::OutArg>,
67    /// The number of subqueries of `FROM` that the planner merged into the query, which stay in the range table of PostgreSQL with no plan.
68    pub pulled: usize,
69    /// True when each condition of `WHERE` is a condition of the query above that the planner moved into the query, which had no `WHERE`. A `SELECT` of a `UNION ALL` with no `WHERE` is a member of the append relation, as `is_safe_append_member` lets it.
70    pub pushed: bool,
71    /// For an `UPDATE` or a `DELETE` of a view, and for a `SELECT` whose view with `security_barrier` the executor merged, the number of the parts of `AND` of the condition of each view with `security_barrier`, the inner view first. These conditions come first in [`Query::filter`], and they have the `security_level` of `securityQuals`: the conditions of a view run before the conditions of the views above it and of the statement, as `order_qual_clauses` orders them.
72    pub barrier: Vec<usize>,
73    /// The queries of `preprocess_minmax_aggregates` for a query whose aggregate calls are each `min` or `max` of one table, which the planner can run as an `InitPlan` that reads the first row of an index.
74    pub minmax: Option<Box<MinMax>>,
75    /// `constraintDeps`: the OIDs of the primary keys that make columns of `GROUP BY` queries valid, which a view depends on.
76    pub constraint_deps: Vec<u32>,
77    /// For the query of `RETURNING`, the list as `EXPLAIN` shows it.
78    pub shown: Option<Box<crate::Shown>>,
79    /// `rteperminfos`: the privileges that the statement needs on each relation that it reads or writes, also in its subqueries and in the queries of its views. Only the top query of a statement has them.
80    pub perms: Vec<crate::PermInfo>,
81    /// The OIDs of the functions and of the functions of the operators that the statement calls, also in its subqueries and in the queries of its views, as `ExecInitFunc` checks `EXECUTE` on them. Only the top query of a statement has them.
82    pub funcs: Vec<u32>,
83}
84
85/// `MinMaxAggInfo`: the form of a query whose aggregate calls are each `min` or `max`, with a subquery for each aggregate call that reads the first value in the order of its sort operator.
86#[derive(Clone, Debug, PartialEq)]
87pub struct MinMax {
88    /// The two subqueries of each aggregate call that is not the same as an earlier one: the first one has the nulls first for `max` and last for `min`, as `build_minmax_path` tries it first, and the second one has the other order of the nulls.
89    pub aggs: Vec<[Query; 2]>,
90    /// The targets of the query, with a subquery of `aggs` in the place of each aggregate call. A subquery is the first subquery of its aggregate call.
91    pub targets: Vec<Expr>,
92    /// The `HAVING` condition of the query with the same subqueries.
93    pub having: Option<Expr>,
94}
95
96/// A column of the result.
97#[derive(Clone, Debug, PartialEq)]
98pub struct Target {
99    /// The name of the column in `RowDescription`.
100    pub name: String,
101    pub expr: Expr,
102    /// The OID of the table and the attribute number of the column when the target is a plain column, as `resorigtbl` and `resorigcol`.
103    pub origin: Option<(u32, i16)>,
104    /// `resjunk`: true for a column that only `ORDER BY` or `GROUP BY` reads, which the result does not show.
105    pub junk: bool,
106}
107
108impl Query {
109    /// The expressions of the query, in the order of `query_tree_walker`: the targets, the conditions of the joins, `WHERE`, `HAVING`, `OFFSET`, `LIMIT`, the offsets of the frames of the windows, the calls of the functions in `FROM`, the rows of the `VALUES` lists and the arguments of `TABLESAMPLE`.
110    pub fn exprs(&self) -> Vec<&Expr> {
111        fn joins<'a>(item: &'a FromItem, out: &mut Vec<&'a Expr>) {
112            if let FromItem::Join(j) = item {
113                joins(&j.left, out);
114                joins(&j.right, out);
115                out.extend(&j.on);
116            }
117        }
118        let mut out: Vec<&Expr> = self.targets.iter().map(|t| &t.expr).collect();
119        for item in &self.from {
120            joins(item, &mut out);
121        }
122        out.extend(self.filter.iter().chain(&self.having).chain(&self.offset).chain(&self.limit));
123        for window in &self.windows {
124            out.extend(window.frame.start.iter().chain(&window.frame.end));
125        }
126        for relation in &self.relations {
127            if let Some(function) = &relation.function {
128                out.extend(function.calls.iter().map(|(call, _)| call));
129            }
130            out.extend(relation.values.iter().flatten().flatten());
131            if let Some(sample) = &relation.tablesample {
132                out.extend(sample.args.iter().chain(&sample.repeatable));
133            }
134        }
135        out
136    }
137
138    /// The expressions of the query, in the order of [`Query::exprs`].
139    pub fn exprs_mut(&mut self) -> Vec<&mut Expr> {
140        fn joins<'a>(item: &'a mut FromItem, out: &mut Vec<&'a mut Expr>) {
141            if let FromItem::Join(j) = item {
142                let j = &mut **j;
143                joins(&mut j.left, out);
144                joins(&mut j.right, out);
145                out.extend(&mut j.on);
146            }
147        }
148        let mut out: Vec<&mut Expr> = self.targets.iter_mut().map(|t| &mut t.expr).collect();
149        for item in &mut self.from {
150            joins(item, &mut out);
151        }
152        out.extend(
153            self.filter
154                .iter_mut()
155                .chain(&mut self.having)
156                .chain(&mut self.offset)
157                .chain(&mut self.limit),
158        );
159        for window in &mut self.windows {
160            out.extend(window.frame.start.iter_mut().chain(&mut window.frame.end));
161        }
162        for relation in &mut self.relations {
163            if let Some(function) = &mut relation.function {
164                out.extend(function.calls.iter_mut().map(|(call, _)| call));
165            }
166            out.extend(relation.values.iter_mut().flatten().flatten());
167            if let Some(sample) = &mut relation.tablesample {
168                out.extend(sample.args.iter_mut().chain(&mut sample.repeatable));
169            }
170        }
171        out
172    }
173
174    /// `hasTargetSRFs`: true when a target calls a function that gives a set.
175    pub fn has_target_srfs(&self) -> bool {
176        self.targets.iter().any(|t| t.expr.first_set_call().is_some())
177    }
178
179    /// The expressions of the query and of its subqueries in `FROM`, each with its depth: `depth` for the query, and one more for each subquery in `FROM` between the expression and the query. The subqueries in `FROM` come after the expressions of the query, as in `query_tree_walker`.
180    pub fn all_exprs(&self, depth: usize) -> Vec<(&Expr, usize)> {
181        let mut out: Vec<(&Expr, usize)> = self.exprs().into_iter().map(|e| (e, depth)).collect();
182        for relation in &self.relations {
183            if let Some(sub) = &relation.subquery {
184                out.extend(sub.all_exprs(depth + 1));
185            }
186        }
187        out
188    }
189
190    /// Calls `f` for each expression of [`Query::all_exprs`], with its depth.
191    pub fn each_expr_mut(&mut self, depth: usize, f: &mut impl FnMut(&mut Expr, usize)) {
192        for expr in self.exprs_mut() {
193            f(expr, depth);
194        }
195        for relation in &mut self.relations {
196            if let Some(sub) = &mut relation.subquery {
197                sub.each_expr_mut(depth + 1, f);
198            }
199        }
200    }
201}
202
203/// The error of a clause that the analyzer does not take yet.
204fn not_yet(what: &str) -> Error {
205    Error::new(SqlState::FEATURE_NOT_SUPPORTED, format!("{what} is not supported yet"))
206}
207
208impl Analyzer<'_> {
209    /// The query tree of a `SELECT`.
210    pub(crate) fn select(&mut self, s: &SelectStmt) -> Result<Query> {
211        // A `SELECT` of a set operation keeps its columns of type `unknown`, so that the operation can give them a type.
212        let keep_unknowns = std::mem::take(&mut self.keep_unknowns);
213        let parent = self.parent_cte.take();
214        if let Some(with) = s.withClause.as_deref() {
215            self.transform_with(with)?;
216        }
217        let mut query = if s.op != SetOperation::SETOP_NONE {
218            self.set_operation(s, parent)?
219        } else if !s.valuesLists.is_empty() {
220            self.values_clause(s)?
221        } else {
222            self.simple_select(s, keep_unknowns)?
223        };
224        query.recursive = s.withClause.as_deref().is_some_and(|w| w.recursive);
225        query.ctes = self.take_ctes()?;
226        Ok(query)
227    }
228
229    /// `transformTargetList`: the targets of a list of `ResTarget` items in the place `kind`, with `*` and `x.*` expanded to their columns.
230    pub(crate) fn target_list(&mut self, list: &List, kind: Kind) -> Result<Vec<Target>> {
231        let mut targets = Vec::with_capacity(list.len());
232        for target in list {
233            let Some(Node::ResTarget(rt)) = target else {
234                return Err(Error::internal("a target that is not ResTarget"));
235            };
236            if let Some(Node::ColumnRef(c)) = &rt.val
237                && let Some(columns) = self.expand_star(c)?
238            {
239                for (name, expr) in columns {
240                    targets.push(Target { name, expr, origin: None, junk: false });
241                }
242                continue;
243            }
244            if let Some(Node::A_Indirection(ind)) = &rt.val
245                && let Some(fields) = self.with_kind(kind, |a| a.expand_indirection_star(ind))?
246            {
247                for (name, expr) in fields {
248                    targets.push(Target { name, expr, origin: None, junk: false });
249                }
250                continue;
251            }
252            let expr = self.with_kind(kind, |a| a.transform(rt.val.as_ref()))?;
253            let name = match &rt.name {
254                Some(name) => name.to_string(),
255                None => figure_colname(rt.val.as_ref()),
256            };
257            targets.push(Target { name, expr, origin: None, junk: false });
258        }
259        Ok(targets)
260    }
261
262    /// `markTargetListOrigins`: a target that is a column of a relation names the table and the column, also for a column of a query outside this query. A column of a view is a column of the view. A column of a subquery in FROM has the origin of the column of the subquery, and a column of a function in FROM has no origin.
263    pub(crate) fn mark_origins(&self, targets: &mut [Target]) {
264        for target in targets {
265            if let ExprKind::Var(var) = &target.expr.kind {
266                let relation = &self.level(var.levels_up).relations[var.relation];
267                let written = relation.cte.as_ref().filter(|c| c.write.is_some());
268                target.origin = match (&relation.subquery, written) {
269                    (None, Some(cte)) => usize::try_from(var.attnum - 1)
270                        .ok()
271                        .and_then(|i| cte.origins.get(i).copied().flatten()),
272                    (None, None)
273                        if relation.function.is_some()
274                            || relation.values.is_some()
275                            || relation.cte.is_some() =>
276                    {
277                        None
278                    }
279                    (None, None) => Some((relation.oid, var.attnum)),
280                    (Some(_), _) if relation.oid != 0 => Some((relation.oid, var.attnum)),
281                    (Some(sub), _) => usize::try_from(var.attnum - 1)
282                        .ok()
283                        .and_then(|i| sub.targets.iter().filter(|t| !t.junk).nth(i))
284                        .and_then(|t| t.origin),
285                };
286            }
287        }
288    }
289
290    /// The query tree of a `SELECT` that is not a set operation or a `VALUES` list, with its windows.
291    fn simple_select(&mut self, s: &SelectStmt, keep_unknowns: bool) -> Result<Query> {
292        if s.intoClause.is_some() {
293            return Err(not_yet("SELECT INTO"));
294        }
295        // The windows of the `WINDOW` clause come first, and each query has its own windows.
296        let defs = s.windowClause.iter().flatten().filter_map(|node| match node {
297            Node::WindowDef(def) => Some((**def).clone()),
298            _ => None,
299        });
300        let windowdefs = std::mem::replace(&mut self.windowdefs, defs.collect());
301        let has_windows = std::mem::replace(&mut self.has_windows, false);
302        let result = self.plain_select(s, keep_unknowns);
303        self.windowdefs = windowdefs;
304        self.has_windows = has_windows;
305        result
306    }
307
308    /// The query tree of a `SELECT` that is not a set operation or a `VALUES` list.
309    fn plain_select(&mut self, s: &SelectStmt, keep_unknowns: bool) -> Result<Query> {
310        // The subqueries of the query are not the value of the assignment.
311        let assign = self.assign.take();
312        let from = self.transform_from(&s.fromClause)?;
313        let mut targets = self.target_list(&s.targetList, Kind::Select)?;
314        if let Some(assign) = assign {
315            self.assign_target(&mut targets, assign)?;
316        }
317        let filter = match &s.whereClause {
318            Some(node) => {
319                let expr = self.with_kind(Kind::Where, |a| a.transform(Some(node)))?;
320                Some(self.coerce_to_boolean(expr, "WHERE")?)
321            }
322            None => None,
323        };
324        let mut having = match &s.havingClause {
325            Some(node) => {
326                let expr = self.with_kind(Kind::Having, |a| a.transform(Some(node)))?;
327                Some(self.coerce_to_boolean(expr, "HAVING")?)
328            }
329            None => None,
330        };
331        self.mark_origins(&mut targets);
332        let sort = self.sort_clause(&s.sortClause, &mut targets)?;
333        let (group, mut grouping_sets) = self.group_clause(&s.groupClause, &mut targets, &sort)?;
334        // The parser gives a list with one null item for `DISTINCT` and the expressions for `DISTINCT ON`.
335        let distinct_on = matches!(s.distinctClause.first(), Some(Some(_)));
336        let distinct = if s.distinctClause.is_empty() {
337            Vec::new()
338        } else if distinct_on {
339            self.distinct_on_clause(&s.distinctClause, &mut targets, &sort)?
340        } else {
341            self.distinct_clause(&mut targets, &sort, false)?
342        };
343        let with_ties = s.limitOption == LimitOption::LIMIT_OPTION_WITH_TIES;
344        let offset = self.with_kind(Kind::Offset, |a| {
345            a.limit_clause(s.limitOffset.as_ref(), "OFFSET", with_ties)
346        })?;
347        let limit = self.with_kind(Kind::Limit, |a| {
348            a.limit_clause(s.limitCount.as_ref(), "LIMIT", with_ties)
349        })?;
350        let windows = self.window_clauses(&mut targets)?;
351        // `resolveTargetListUnknowns`: a column of type `unknown` becomes `text`.
352        for target in targets.iter_mut().filter(|_| !keep_unknowns) {
353            if target.expr.ty == oid::UNKNOWN {
354                let expr = std::mem::replace(&mut target.expr, Expr::new(ExprKind::CaseTest, 0));
355                target.expr = self.coerce(expr, oid::TEXT, -1, Context::Implicit, None)?;
356            }
357        }
358        let group_distinct = s.groupDistinct;
359        let grouped =
360            self.has_aggs || !group.is_empty() || !grouping_sets.is_empty() || having.is_some();
361        let mut constraint_deps = Vec::new();
362        if grouped {
363            constraint_deps = self.check_grouping(
364                &mut targets,
365                having.as_mut(),
366                &group,
367                &mut grouping_sets,
368                group_distinct,
369            )?;
370        }
371        let relations = std::mem::take(&mut self.scope.relations);
372        let mut query = Query {
373            relations,
374            from,
375            targets,
376            filter,
377            grouped,
378            group,
379            grouping_sets,
380            group_distinct,
381            having,
382            sort,
383            distinct,
384            distinct_on,
385            offset,
386            limit,
387            with_ties,
388            params: Vec::new(),
389            notices: Vec::new(),
390            set_op: None,
391            windows,
392            ctes: Vec::new(),
393            recursive: false,
394            row_marks: Vec::new(),
395            write: None,
396            out_args: Vec::new(),
397            pulled: 0,
398            pushed: false,
399            barrier: Vec::new(),
400            minmax: None,
401            constraint_deps,
402            shown: None,
403            perms: Vec::new(),
404            funcs: Vec::new(),
405        };
406        for clause in s.lockingClause.iter().flatten() {
407            if let Node::LockingClause(clause) = clause {
408                crate::locking::transform_locking_clause(&mut query, clause)?;
409            }
410        }
411        if !s.lockingClause.is_empty() {
412            self.mark_locked(&query);
413        }
414        Ok(query)
415    }
416}