Skip to main content

rupg_func/deparse/
query.rs

1//! `pg_get_viewdef` and the parts of `ruleutils.c` that show a query: `get_query_def`, the target list, `FROM`, the set operations, `ORDER BY`, the aggregate calls, the subqueries and the calls in the special syntax of the SQL standard.
2//!
3//! rupg keeps the text of the statement that made a view, not its query tree. So `pg_get_viewdef` analyzes the text again, with the `search_path` that the statement had, and shows the query as PostgreSQL shows the query tree that it keeps.
4
5use std::collections::HashMap;
6
7use rupg_analyze::{
8    Column, Cte, FRAMEOPTION_END_OFFSET, FRAMEOPTION_END_UNBOUNDED_FOLLOWING,
9    FRAMEOPTION_START_OFFSET, Frame, FromFunction, FromItem, GroupingSet, Join, JoinKind, JoinRow,
10    NullTreatment, Query, Relation, SetKind, SetOp, SetTree, TableSample,
11};
12use rupg_sql::nodes::{
13    FRAMEOPTION_BETWEEN, FRAMEOPTION_END_CURRENT_ROW, FRAMEOPTION_END_OFFSET_PRECEDING,
14    FRAMEOPTION_EXCLUDE_CURRENT_ROW, FRAMEOPTION_EXCLUDE_GROUP, FRAMEOPTION_EXCLUDE_TIES,
15    FRAMEOPTION_NONDEFAULT, FRAMEOPTION_RANGE, FRAMEOPTION_ROWS, FRAMEOPTION_START_CURRENT_ROW,
16    FRAMEOPTION_START_OFFSET_PRECEDING, FRAMEOPTION_START_UNBOUNDED_PRECEDING,
17};
18use rupg_types::qualified_name_list;
19
20use super::{
21    Aggref, Deparser, Error, Expr, ExprKind, Func, FuncForm, INDENT_STD, INDENT_VAR, JoinNames,
22    JsonCtor, Namespace, Result, SortGroup, SubLink, SubLinkKind, Value, WindowClause, WindowFunc,
23    builtin, column_names, json_format, looks_like_function, oid, pretty_arg,
24    qualified_relation_name, quote_identifier, reg, relation_name, sort_operators,
25};
26use crate::{Call, Session, bad_value, not_yet, type_error};
27use rupg_catalog::{
28    TRIGGER_BEFORE, TRIGGER_DELETE, TRIGGER_INSERT, TRIGGER_INSTEAD, TRIGGER_ROW, TRIGGER_TRUNCATE,
29    TRIGGER_UPDATE,
30};
31
32/// `PRETTYINDENT_JOIN`: the indent of a `JOIN` keyword after the start of its line.
33const INDENT_JOIN: i32 = 4;
34/// `F_UNNEST_ANYARRAY`: the function `unnest(anyarray)`.
35const UNNEST: u32 = 2331;
36
37impl Deparser<'_> {
38    /// `get_query_def`: the query with the names of its relations, in the queries outside it. `result` has the names of the columns of the result when the caller knows them, and `indent` is the indent of the query.
39    pub(super) fn query_def(
40        &mut self,
41        query: &Query,
42        result: Option<&[String]>,
43        names_visible: bool,
44        indent: i32,
45    ) -> Result<()> {
46        let space = self.namespace(query);
47        let joins: usize = query.from.iter().map(join_count).sum();
48        // The body of a function in SQL has the namespace of the function outside the query.
49        let prefix = !self.namespaces.is_empty()
50            || self.function.is_some()
51            || query.relations.len() + joins != 1;
52        let outputs = query
53            .targets
54            .iter()
55            .filter(|t| !t.junk)
56            .enumerate()
57            .map(|(i, t)| {
58                let name = result.and_then(|r| r.get(i)).unwrap_or(&t.name).clone();
59                let var = match &t.expr.kind {
60                    ExprKind::Var(var) => Some(*var),
61                    _ => None,
62                };
63                (name, var)
64            })
65            .collect();
66        let saved_indent = std::mem::replace(&mut self.indent, indent);
67        let saved_prefix = std::mem::replace(&mut self.prefix, prefix);
68        let saved_visible = std::mem::replace(&mut self.names_visible, names_visible);
69        let saved_group = std::mem::replace(&mut self.in_group_by, false);
70        let saved_outputs = std::mem::replace(&mut self.outputs, outputs);
71        let saved_windows = std::mem::replace(&mut self.windows, query.windows.clone());
72        let targets = query.targets.iter().map(|t| t.expr.clone()).collect();
73        let saved_targets = std::mem::replace(&mut self.window_targets, targets);
74        self.namespaces.push(space);
75        let done = self.select_query(query, result);
76        self.namespaces.pop();
77        self.windows = saved_windows;
78        self.window_targets = saved_targets;
79        self.indent = saved_indent;
80        self.prefix = saved_prefix;
81        self.names_visible = saved_visible;
82        self.in_group_by = saved_group;
83        self.outputs = saved_outputs;
84        done
85    }
86
87    /// `set_rtable_names`, `set_using_names`, `set_relation_column_names` and `set_join_column_names`: a name for each relation and each join with an alias that no other relation of the query or of the queries outside it has, and the names of the columns of each relation and each join. The names come in the order of the range table, where a join comes after the relations in it.
88    fn namespace(&self, query: &Query) -> Namespace {
89        let mut used: HashMap<String, u32> = HashMap::new();
90        for space in &self.namespaces {
91            let joins = space.joins.iter().filter_map(|j| j.name.as_ref());
92            for name in space.names.iter().filter(|n| !n.is_empty()).chain(joins) {
93                used.insert(name.clone(), 0);
94            }
95        }
96        self.namespace_in(query, &mut used, false, &[])
97    }
98
99    /// The name of a relation before `set_rtable_names` makes it unique: the alias, or else the name of the table.
100    pub(super) fn base_name(&self, rel: &Relation) -> String {
101        match reg::class_name(rel.oid, self.session) {
102            Some((name, _)) if rel.alias.is_none() && rel.oid != 0 => name.to_string(),
103            _ => rel.name.clone(),
104        }
105    }
106
107    /// [`Deparser::namespace`] with the names that are in use. For `EXPLAIN`, as `select_rtable_names_for_explain`, a join has no name, because no node of the plan reads a join, and a column of `USING` shows as its value. The relations in `hidden` take no unique name.
108    pub(super) fn namespace_in(
109        &self,
110        query: &Query,
111        used: &mut HashMap<String, u32>,
112        explain: bool,
113        hidden: &[usize],
114    ) -> Namespace {
115        let mut joins = Vec::new();
116        let mut order = Vec::new();
117        let tops: Vec<Slot> =
118            query.from.iter().map(|item| walk_from(item, &mut joins, &mut order)).collect();
119        let mut seen = vec![false; query.relations.len()];
120        for slot in &order {
121            if let Slot::Relation(i) = slot
122                && let Some(s) = seen.get_mut(*i)
123            {
124                *s = true;
125            }
126        }
127        order.extend(seen.iter().enumerate().filter(|(_, s)| !**s).map(|(i, _)| Slot::Relation(i)));
128        let mut space =
129            Namespace { names: vec![String::new(); query.relations.len()], ..Default::default() };
130        let mut join_names: Vec<Option<String>> = vec![None; joins.len()];
131        // `select_rtable_names_for_explain` names the relations in the order of the range table, where the relations of a subquery that `pull_up_subqueries` merged into the query come last.
132        let mut naming = order.clone();
133        if explain {
134            naming.sort_by_key(|slot| match *slot {
135                Slot::Relation(i) => (!seen[i], i),
136                Slot::Join(_) => (true, usize::MAX),
137            });
138        }
139        for slot in &naming {
140            match *slot {
141                Slot::Relation(i) => {
142                    let Some(rel) = query.relations.get(i) else { continue };
143                    // A relation that the plan does not scan has no name in the range table.
144                    if hidden.contains(&i) {
145                        space.names[i] = self.base_name(rel);
146                        continue;
147                    }
148                    space.names[i] = unique_name(self.base_name(rel), used);
149                }
150                Slot::Join(k) => {
151                    if let Some(alias) = &joins[k].join.alias
152                        && !explain
153                    {
154                        join_names[k] = Some(unique_name(alias.clone(), used));
155                    }
156                }
157            }
158        }
159        let mut state = ColumnNames {
160            relations: query.relations.iter().map(|r| vec![None; r.columns.len()]).collect(),
161            relation_parents: vec![Vec::new(); query.relations.len()],
162            joins: joins.iter().map(|j| vec![None; j.join.columns.len()]).collect(),
163            join_parents: vec![Vec::new(); joins.len()],
164            join_using: vec![Vec::new(); joins.len()],
165            using: Vec::new(),
166            unique_using: joins
167                .iter()
168                .any(|j| j.join.alias.is_none() && !j.join.using.is_empty() && !j.join.plain_using),
169        };
170        for slot in tops {
171            if let Slot::Join(k) = slot {
172                state.using_names(&joins, k, &[]);
173            }
174        }
175        // `set_relation_column_names` reads the names of the columns of a table or a view from the catalog, so a column that `ALTER ... RENAME` renamed after the analysis of the query shows its new name. A column that `ALTER TABLE ... ADD COLUMN` added after the analysis has a name too, which the other names of the relation do not have. A dropped column has no name.
176        let catalog = self.session.catalog();
177        let real_names: Vec<Vec<String>> = query
178            .relations
179            .iter()
180            .map(|rel| {
181                let now = catalog
182                    .and_then(|c| c.relation(rel.oid))
183                    .filter(|now| rel.oid != 0 && now.columns.len() >= rel.columns.len());
184                match now {
185                    Some(now) => now
186                        .columns
187                        .iter()
188                        .map(|c| if c.dropped { String::new() } else { c.name.clone() })
189                        .collect(),
190                    None => rel.columns.iter().map(|c| c.name.clone()).collect(),
191                }
192            })
193            .collect();
194        for (names, real) in state.relations.iter_mut().zip(&real_names) {
195            names.resize(real.len().max(names.len()), None);
196        }
197        let mut print_join = vec![false; joins.len()];
198        for slot in &order {
199            match *slot {
200                Slot::Relation(i) => {
201                    let Some(rel) = query.relations.get(i) else { continue };
202                    let given: &[String] = rel.alias.as_deref().unwrap_or_default();
203                    for (c, column) in real_names[i].iter().enumerate() {
204                        if state.relations[i][c].is_none() && column.is_empty() {
205                            state.relations[i][c] = Some(String::new());
206                        } else if state.relations[i][c].is_none() {
207                            let wanted = given.get(c).unwrap_or(column);
208                            let name = state.unique(wanted, Slot::Relation(i));
209                            state.relations[i][c] = Some(name);
210                        }
211                    }
212                }
213                Slot::Join(k) => print_join[k] = state.join_columns(&joins, k),
214            }
215        }
216        for (i, rel) in query.relations.iter().enumerate() {
217            let given: &[String] = rel.alias.as_deref().unwrap_or_default();
218            let names: Vec<String> =
219                state.relations[i].iter().map(|n| n.clone().unwrap_or_default()).collect();
220            // The real name of a column of a table or a view is the name in the catalog. For another relation, it is the name that the alias gives.
221            let changed =
222                real_names[i].iter().zip(&names).enumerate().any(|(c, (column, name))| {
223                    let real = if rel.oid != 0 { column } else { given.get(c).unwrap_or(column) };
224                    name != real
225                });
226            // `JSON_TABLE` does not show the names of its columns after its alias.
227            let print = if rel.json_table().is_some() {
228                false
229            } else if rel.oid != 0 {
230                changed
231            } else {
232                rel.function.is_some() || !given.is_empty() || changed
233            };
234            space.columns.push(names);
235            space.print_aliases.push(print);
236        }
237        for (k, info) in joins.iter().enumerate() {
238            space.joins.push(JoinNames {
239                name: join_names[k].clone(),
240                relations: info.relations.clone(),
241                columns: state.joins[k].iter().map(|n| n.clone().unwrap_or_default()).collect(),
242                using: std::mem::take(&mut state.join_using[k]),
243                values: info.join.columns.iter().map(|(_, e)| e.clone()).collect(),
244                print_aliases: print_join[k],
245            });
246        }
247        if !explain {
248            for item in &query.from {
249                merged_columns(item, &mut space.merged);
250            }
251        }
252        space.relations.clone_from(&query.relations);
253        space
254    }
255
256    /// `get_variable` for a column of a join with an alias: the name of the join and the name of the column, when the expression is the value of a column of a join with an alias outside the part of `FROM` that the deparse shows now. The alias hides the relations in the join, so the query reads such a column through the join.
257    pub(super) fn join_column(&self, e: &Expr) -> Option<(String, String)> {
258        for (levels, space) in self.namespaces.iter().rev().enumerate() {
259            for (k, join) in space.joins.iter().enumerate() {
260                let Some(name) = &join.name else { continue };
261                if space.inside.contains(&k) {
262                    continue;
263                }
264                for (value, column) in join.values.iter().zip(&join.columns) {
265                    let found = match (&value.kind, &e.kind) {
266                        (ExprKind::Var(v), ExprKind::Var(w)) => {
267                            v.relation == w.relation
268                                && v.attnum == w.attnum
269                                && v.levels_up + levels == w.levels_up
270                        }
271                        (ExprKind::Var(_), _) | (_, ExprKind::Var(_)) => false,
272                        _ if std::mem::discriminant(&value.kind)
273                            != std::mem::discriminant(&e.kind) =>
274                        {
275                            false
276                        }
277                        _ => {
278                            let mut value = value.clone();
279                            value.raise(levels);
280                            value.same(e)
281                        }
282                    };
283                    if found {
284                        return Some((name.clone(), column.clone()));
285                    }
286                }
287            }
288        }
289        None
290    }
291
292    /// The name of the join with an alias that gives the fields of a whole row, or the alias of the analyzer when no join of the queries gives them.
293    pub(super) fn join_row_name(&self, row: &JoinRow) -> String {
294        for (levels, space) in self.namespaces.iter().rev().enumerate() {
295            for join in &space.joins {
296                let Some(name) = &join.name else { continue };
297                let same = join.values.len() == row.fields.len()
298                    && join.values.iter().zip(&row.fields).all(|(value, field)| {
299                        let mut value = value.clone();
300                        value.raise(levels);
301                        value.same(field)
302                    });
303                if same {
304                    return name.clone();
305                }
306            }
307        }
308        row.alias.clone().unwrap_or_default()
309    }
310
311    /// The name of a column of `USING` that is not a column of one side, or of a column of a join with an alias, when the expression is its value in this query or in a query outside it.
312    pub(super) fn merged_name(&self, e: &Expr) -> Option<String> {
313        if let Some((_, column)) = self.join_column(e) {
314            return Some(column);
315        }
316        for (levels, space) in self.namespaces.iter().rev().enumerate() {
317            for (value, name) in &space.merged {
318                let found = if levels == 0 {
319                    value.same(e)
320                } else {
321                    let mut value = value.clone();
322                    value.raise(levels);
323                    value.same(e)
324                };
325                if found {
326                    return Some(name.clone());
327                }
328            }
329        }
330        None
331    }
332
333    /// `get_select_query_def`: the query, then `ORDER BY`, `OFFSET` and `LIMIT`.
334    fn select_query(&mut self, query: &Query, result: Option<&[String]>) -> Result<()> {
335        self.with_clause(query)?;
336        let force = match &query.set_op {
337            Some(op) => {
338                self.set_op(op, query, result)?;
339                true
340            }
341            None => {
342                self.basic_select(query, result)?;
343                false
344            }
345        };
346        if !query.sort.is_empty() {
347            self.keyword(" ORDER BY ", -INDENT_STD, INDENT_STD, 1);
348            let exprs: Vec<&Expr> = query.targets.iter().map(|t| &t.expr).collect();
349            self.order_by(&query.sort, &exprs, force)?;
350        }
351        if let Some(offset) = &query.offset {
352            self.keyword(" OFFSET ", -INDENT_STD, INDENT_STD, 0);
353            self.expr(offset, false)?;
354        }
355        if let Some(limit) = &query.limit {
356            if query.with_ties {
357                self.keyword(" FETCH FIRST ", -INDENT_STD, INDENT_STD, 0);
358                self.buf.push('(');
359                self.expr(limit, false)?;
360                self.buf.push_str(") ROWS WITH TIES");
361            } else {
362                self.keyword(" LIMIT ", -INDENT_STD, INDENT_STD, 0);
363                match &limit.kind {
364                    ExprKind::Const(value) if value.is_null() => self.buf.push_str("ALL"),
365                    _ => self.expr(limit, false)?,
366                }
367            }
368        }
369        Ok(())
370    }
371
372    /// `get_with_clause`: the queries of `WITH`, each in parentheses on its own lines.
373    fn with_clause(&mut self, query: &Query) -> Result<()> {
374        if query.ctes.is_empty() {
375            return Ok(());
376        }
377        self.indent += INDENT_STD;
378        if !self.flat {
379            self.buf.push(' ');
380        }
381        let mut sep = if query.recursive { "WITH RECURSIVE " } else { "WITH " };
382        for cte in &query.ctes {
383            self.buf.push_str(sep);
384            self.buf.push_str(&quote_identifier(&cte.name));
385            if !cte.aliases.is_empty() {
386                let names: Vec<String> = cte.aliases.iter().map(|n| quote_identifier(n)).collect();
387                self.buf.push_str(&format!("({})", names.join(", ")));
388            }
389            self.buf.push_str(" AS ");
390            match cte.materialized {
391                Some(true) => self.buf.push_str("MATERIALIZED "),
392                Some(false) => self.buf.push_str("NOT MATERIALIZED "),
393                None => {}
394            }
395            self.buf.push('(');
396            self.keyword("", 0, 0, 0);
397            self.query_def(&cte.query, None, true, self.indent)?;
398            self.keyword("", 0, 0, 0);
399            self.buf.push(')');
400            self.search_cycle(cte)?;
401            sep = ", ";
402        }
403        self.indent -= INDENT_STD;
404        self.keyword("", 0, 0, 0);
405        Ok(())
406    }
407
408    /// The `SEARCH` and `CYCLE` clauses of a query of `WITH`. `CYCLE` shows `TO` and `DEFAULT` unless the marks are `true` and `false`.
409    fn search_cycle(&mut self, cte: &Cte) -> Result<()> {
410        let names = |list: &[String]| -> String {
411            list.iter().map(|n| quote_identifier(n)).collect::<Vec<_>>().join(", ")
412        };
413        if let Some(s) = &cte.search {
414            let order = if s.breadth { "BREADTH" } else { "DEPTH" };
415            let columns = names(&s.columns);
416            let seq = quote_identifier(&s.seq);
417            self.buf.push_str(&format!(" SEARCH {order} FIRST BY {columns} SET {seq}"));
418        }
419        if let Some(c) = &cte.cycle {
420            let columns = names(&c.columns);
421            let mark = quote_identifier(&c.mark);
422            self.buf.push_str(&format!(" CYCLE {columns} SET {mark}"));
423            let plain = matches!(c.value.kind, ExprKind::Const(Value::Bool(true)))
424                && matches!(c.default.kind, ExprKind::Const(Value::Bool(false)))
425                && c.ty == oid::BOOL;
426            if !plain {
427                self.buf.push_str(" TO ");
428                self.expr(&c.value, false)?;
429                self.buf.push_str(" DEFAULT ");
430                self.expr(&c.default, false)?;
431            }
432            self.buf.push_str(&format!(" USING {}", quote_identifier(&c.path)));
433        }
434        Ok(())
435    }
436
437    /// `get_basic_select_query`: a `SELECT` with no set operation, or a plain `VALUES` list.
438    fn basic_select(&mut self, query: &Query, result: Option<&[String]>) -> Result<()> {
439        self.indent += INDENT_STD;
440        if !self.flat {
441            self.buf.push(' ');
442        }
443        if let Some(rows) = simple_values(query, result) {
444            return self.values(rows);
445        }
446        self.buf.push_str("SELECT");
447        if !query.distinct.is_empty() {
448            if query.distinct_on {
449                self.buf.push_str(" DISTINCT ON (");
450                for (i, item) in query.distinct.iter().enumerate() {
451                    if i > 0 {
452                        self.buf.push_str(", ");
453                    }
454                    let e = target_expr(query, item)?;
455                    self.sort_group(e, item.target + 1, false)?;
456                }
457                self.buf.push(')');
458            } else {
459                self.buf.push_str(" DISTINCT");
460            }
461        }
462        self.target_list(query, result)?;
463        self.clause_from(query)?;
464        if let Some(filter) = &query.filter {
465            self.keyword(" WHERE ", -INDENT_STD, INDENT_STD, 1);
466            self.expr(filter, false)?;
467        }
468        if !query.group.is_empty() || !query.grouping_sets.is_empty() {
469            self.keyword(" GROUP BY ", -INDENT_STD, INDENT_STD, 1);
470            if query.group_distinct {
471                self.buf.push_str("DISTINCT ");
472            }
473            let saved = std::mem::replace(&mut self.in_group_by, true);
474            if query.grouping_sets.is_empty() {
475                for (i, item) in query.group.iter().enumerate() {
476                    if i > 0 {
477                        self.buf.push_str(", ");
478                    }
479                    let e = target_expr(query, item)?;
480                    self.sort_group(e, item.target + 1, false)?;
481                }
482            } else {
483                for (i, set) in query.grouping_sets.iter().enumerate() {
484                    if i > 0 {
485                        self.buf.push_str(", ");
486                    }
487                    self.grouping_set(query, set, true)?;
488                }
489            }
490            self.in_group_by = saved;
491        }
492        if let Some(having) = &query.having {
493            self.keyword(" HAVING ", -INDENT_STD, INDENT_STD, 0);
494            self.expr(having, false)?;
495        }
496        // get_rule_windowclause: the windows with a name.
497        let mut first = true;
498        for window in &query.windows {
499            let Some(name) = &window.name else { continue };
500            if first {
501                self.keyword(" WINDOW ", -INDENT_STD, INDENT_STD, 1);
502            } else {
503                self.buf.push_str(", ");
504            }
505            first = false;
506            self.buf.push_str(&format!("{} AS ", quote_identifier(name)));
507            self.window_spec(window)?;
508        }
509        Ok(())
510    }
511
512    /// `get_rule_windowspec`: the window in parentheses. The items of `PARTITION BY` show only for a window that copies no window, and the items of `ORDER BY` show only when they are not a copy.
513    fn window_spec(&mut self, window: &WindowClause) -> Result<()> {
514        let targets = std::mem::take(&mut self.window_targets);
515        let exprs: Vec<&Expr> = targets.iter().collect();
516        let done = self.window_parts(window, &exprs);
517        self.window_targets = targets;
518        done
519    }
520
521    /// The parts of [`Deparser::window_spec`], with the expressions of the targets.
522    fn window_parts(&mut self, window: &WindowClause, exprs: &[&Expr]) -> Result<()> {
523        self.buf.push('(');
524        let mut space = false;
525        if let Some(refname) = &window.refname {
526            self.buf.push_str(&quote_identifier(refname));
527            space = true;
528        }
529        if !window.partition.is_empty() && window.refname.is_none() {
530            if space {
531                self.buf.push(' ');
532            }
533            self.buf.push_str("PARTITION BY ");
534            for (i, item) in window.partition.iter().enumerate() {
535                if i > 0 {
536                    self.buf.push_str(", ");
537                }
538                let e = exprs
539                    .get(item.target)
540                    .ok_or_else(|| Error::internal("an item of PARTITION BY with no expression"))?;
541                self.sort_group(e, item.target + 1, false)?;
542            }
543            space = true;
544        }
545        if !window.order.is_empty() && !window.copied_order {
546            if space {
547                self.buf.push(' ');
548            }
549            self.buf.push_str("ORDER BY ");
550            self.order_by(&window.order, exprs, false)?;
551            space = true;
552        }
553        if window.frame.options & FRAMEOPTION_NONDEFAULT != 0 {
554            if space {
555                self.buf.push(' ');
556            }
557            self.frame(&window.frame)?;
558        }
559        self.buf.push(')');
560        Ok(())
561    }
562
563    /// `get_window_frame_options`: the mode of the frame, its bounds and its exclusion.
564    pub(super) fn frame(&mut self, frame: &Frame) -> Result<()> {
565        let options = frame.options;
566        self.buf.push_str(if options & FRAMEOPTION_RANGE != 0 {
567            "RANGE "
568        } else if options & FRAMEOPTION_ROWS != 0 {
569            "ROWS "
570        } else {
571            "GROUPS "
572        });
573        if options & FRAMEOPTION_BETWEEN != 0 {
574            self.buf.push_str("BETWEEN ");
575        }
576        if options & FRAMEOPTION_START_UNBOUNDED_PRECEDING != 0 {
577            self.buf.push_str("UNBOUNDED PRECEDING ");
578        } else if options & FRAMEOPTION_START_CURRENT_ROW != 0 {
579            self.buf.push_str("CURRENT ROW ");
580        } else if options & FRAMEOPTION_START_OFFSET != 0 {
581            let offset = frame
582                .start
583                .as_ref()
584                .ok_or_else(|| Error::internal("a frame start with no offset"))?;
585            self.expr(offset, false)?;
586            self.buf.push_str(if options & FRAMEOPTION_START_OFFSET_PRECEDING != 0 {
587                " PRECEDING "
588            } else {
589                " FOLLOWING "
590            });
591        }
592        if options & FRAMEOPTION_BETWEEN != 0 {
593            self.buf.push_str("AND ");
594            if options & FRAMEOPTION_END_UNBOUNDED_FOLLOWING != 0 {
595                self.buf.push_str("UNBOUNDED FOLLOWING ");
596            } else if options & FRAMEOPTION_END_CURRENT_ROW != 0 {
597                self.buf.push_str("CURRENT ROW ");
598            } else if options & FRAMEOPTION_END_OFFSET != 0 {
599                let offset = frame
600                    .end
601                    .as_ref()
602                    .ok_or_else(|| Error::internal("a frame end with no offset"))?;
603                self.expr(offset, false)?;
604                self.buf.push_str(if options & FRAMEOPTION_END_OFFSET_PRECEDING != 0 {
605                    " PRECEDING "
606                } else {
607                    " FOLLOWING "
608                });
609            }
610        }
611        if options & FRAMEOPTION_EXCLUDE_CURRENT_ROW != 0 {
612            self.buf.push_str("EXCLUDE CURRENT ROW ");
613        } else if options & FRAMEOPTION_EXCLUDE_GROUP != 0 {
614            self.buf.push_str("EXCLUDE GROUP ");
615        } else if options & FRAMEOPTION_EXCLUDE_TIES != 0 {
616            self.buf.push_str("EXCLUDE TIES ");
617        }
618        // Each part ends with a space, and the last one does not keep it.
619        self.buf.pop();
620        Ok(())
621    }
622
623    /// `get_windowfunc_expr`: a call of a window function, then `OVER` and the name of its window or the window in parentheses.
624    pub(super) fn window_func(&mut self, w: &WindowFunc) -> Result<()> {
625        self.window_func_as(w, None)
626    }
627
628    /// `get_windowfunc_expr_helper`: a call of a window function. `json` has the name, the options and the kind of a SQL/JSON aggregate, where `JSON_OBJECTAGG` puts ` : ` between its two arguments.
629    pub(super) fn window_func_as(
630        &mut self,
631        w: &WindowFunc,
632        json: Option<(&str, &str, bool)>,
633    ) -> Result<()> {
634        match json {
635            Some((name, _, _)) => self.buf.push_str(name),
636            None => {
637                let proc = builtin::proc_by_oid(w.oid).ok_or_else(|| {
638                    Error::internal(format!("cache lookup failed for function {}", w.oid))
639                })?;
640                self.buf.push_str(&quote_identifier(proc.name));
641            }
642        }
643        self.buf.push('(');
644        if w.star {
645            self.buf.push('*');
646        } else if let Some((_, _, true)) = json {
647            let [key, value, ..] = w.args.as_slice() else {
648                return Err(Error::internal("JSON_OBJECTAGG with less than two arguments"));
649            };
650            self.expr(key, false)?;
651            self.buf.push_str(" : ");
652            self.expr(value, false)?;
653        } else {
654            for (i, arg) in w.args.iter().enumerate() {
655                if i > 0 {
656                    self.buf.push_str(", ");
657                }
658                self.expr(arg, true)?;
659            }
660        }
661        if let Some((_, options, _)) = json {
662            self.buf.push_str(options);
663        }
664        if let Some(filter) = &w.filter {
665            self.buf.push_str(") FILTER (WHERE ");
666            self.expr(filter, false)?;
667        }
668        self.buf.push_str(") ");
669        if w.nulls == NullTreatment::Ignore {
670            self.buf.push_str("IGNORE NULLS ");
671        }
672        self.buf.push_str("OVER ");
673        if let Some(Some(name)) = w.winref.checked_sub(1).and_then(|i| self.window_names.get(i)) {
674            self.buf.push_str(&quote_identifier(name));
675            return Ok(());
676        }
677        let window = w.winref.checked_sub(1).and_then(|i| self.windows.get(i)).cloned();
678        let Some(window) = window else {
679            return Err(Error::internal(format!(
680                "could not find window clause for winref {}",
681                w.winref
682            )));
683        };
684        match &window.name {
685            Some(name) => self.buf.push_str(&quote_identifier(name)),
686            None => self.window_spec(&window)?,
687        }
688        Ok(())
689    }
690
691    /// `get_values_def`: the rows of a `VALUES` list.
692    fn values(&mut self, rows: &[Vec<Expr>]) -> Result<()> {
693        self.buf.push_str("VALUES ");
694        for (i, row) in rows.iter().enumerate() {
695            if i > 0 {
696                self.buf.push_str(", ");
697            }
698            self.buf.push('(');
699            for (j, value) in row.iter().enumerate() {
700                if j > 0 {
701                    self.buf.push(',');
702                }
703                self.expr(value, false)?;
704            }
705            self.buf.push(')');
706        }
707        Ok(())
708    }
709
710    /// `get_target_list`: the columns of the result, each with `AS name` when its text does not give the name. A column after the first starts a new line when the line gets longer than the wrap column.
711    fn target_list(&mut self, query: &Query, result: Option<&[String]>) -> Result<()> {
712        let mut multiline = false;
713        for (i, target) in query.targets.iter().filter(|t| !t.junk).enumerate() {
714            self.buf.push_str(if i == 0 { " " } else { ", " });
715            let outer = std::mem::take(&mut self.buf);
716            let merged = self.merged_name(&target.expr);
717            let attname = match &target.expr.kind {
718                _ if merged.is_some() => {
719                    self.expr(&target.expr, true)?;
720                    merged
721                }
722                ExprKind::Var(var) if var.attnum == 0 => {
723                    self.whole_row(var, &target.expr, true)?;
724                    if self.names_visible { None } else { Some("?column?".to_string()) }
725                }
726                // `get_variable` shows the type of a whole row in the list of the query.
727                ExprKind::JoinRow(row) if row.alias.is_some() => {
728                    self.expr(&target.expr, true)?;
729                    self.buf.push_str("::record");
730                    if self.names_visible { None } else { Some("?column?".to_string()) }
731                }
732                ExprKind::Var(var) => Some(self.variable(var, false)?),
733                _ => {
734                    self.expr(&target.expr, true)?;
735                    if self.names_visible { None } else { Some("?column?".to_string()) }
736                }
737            };
738            let colname = result.and_then(|r| r.get(i)).unwrap_or(&target.name);
739            if attname.as_deref() != Some(colname.as_str()) {
740                self.buf.push_str(&format!(" AS {}", quote_identifier(colname)));
741            }
742            let item = std::mem::replace(&mut self.buf, outer);
743            if self.wrap >= 0 {
744                let leading = item.starts_with('\n');
745                if leading {
746                    self.trim_spaces();
747                } else if i > 0 && (self.too_long(&item) || multiline) {
748                    self.keyword("", -INDENT_STD, INDENT_STD, INDENT_VAR);
749                }
750                multiline = item[usize::from(leading)..].contains('\n');
751            }
752            self.buf.push_str(&item);
753        }
754        Ok(())
755    }
756
757    /// `removeStringInfoSpaces`.
758    fn trim_spaces(&mut self) {
759        let kept = self.buf.trim_end_matches(' ').len();
760        self.buf.truncate(kept);
761    }
762
763    /// True when the item makes the last line longer than the wrap column.
764    fn too_long(&self, item: &str) -> bool {
765        let line = self.buf.rsplit('\n').next().map_or(0, str::len);
766        usize::try_from(self.wrap).is_ok_and(|wrap| line + item.len() > wrap)
767    }
768
769    /// `get_from_clause`: the items of `FROM`. An item after the first starts a new line when the line gets longer than the wrap column.
770    fn clause_from(&mut self, query: &Query) -> Result<()> {
771        for (i, item) in query.from.iter().enumerate() {
772            if i == 0 {
773                self.keyword(" FROM ", -INDENT_STD, INDENT_STD, 2);
774                self.range_item(item, query)?;
775                continue;
776            }
777            self.buf.push_str(", ");
778            let outer = std::mem::take(&mut self.buf);
779            self.range_item(item, query)?;
780            let text = std::mem::replace(&mut self.buf, outer);
781            if self.wrap >= 0 {
782                if text.starts_with('\n') {
783                    self.trim_spaces();
784                } else if self.too_long(&text) {
785                    self.keyword("", -INDENT_STD, INDENT_STD, INDENT_VAR);
786                }
787            }
788            self.buf.push_str(&text);
789        }
790        Ok(())
791    }
792
793    /// `get_from_clause_item`: a relation with its alias and the names of its columns, or a join.
794    fn range_item(&mut self, item: &FromItem, query: &Query) -> Result<()> {
795        let index = match item {
796            FromItem::Relation(index) => *index,
797            FromItem::Join(join) => return self.join(join, query),
798        };
799        let rel = query
800            .relations
801            .get(index)
802            .ok_or_else(|| Error::internal(format!("no relation {index} in the query")))?;
803        let lateral = rel.lateral
804            || rel.function.as_ref().is_some_and(|f| f.calls.iter().any(|(c, _)| refers_to(c, 0)));
805        if lateral {
806            self.buf.push_str("LATERAL ");
807        }
808        let mut coldef = false;
809        if let Some(cte) = &rel.cte {
810            self.buf.push_str(&quote_identifier(&cte.name));
811        } else if rel.oid != 0 {
812            self.buf.push_str(&relation_name(rel.oid, self.session)?);
813        } else if let Some(table) = rel.json_table() {
814            self.json_table(table)?;
815        } else if let Some(function) = &rel.function {
816            coldef = self.function_item(function, &rel.columns)?;
817        } else if let Some(rows) = &rel.values {
818            self.buf.push('(');
819            self.values(rows)?;
820            self.buf.push(')');
821        } else if let Some(sub) = &rel.subquery {
822            self.buf.push('(');
823            self.query_def(sub, None, true, self.indent)?;
824            self.buf.push(')');
825        }
826        let space = self.namespaces.last().ok_or_else(|| Error::internal("no namespace"))?;
827        let refname = space.names.get(index).cloned().unwrap_or_default();
828        let columns = space.columns.get(index).cloned().unwrap_or_default();
829        let print_aliases = space.print_aliases.get(index).copied().unwrap_or(false);
830        // `get_rte_alias`: a subquery, a function and a `VALUES` list always show their alias, and `JSON_TABLE` shows it only when the query gives one. A table, a view and a query of `WITH` show it when the query gives one or when the name is not the name of the relation.
831        let show = rel.alias.is_some()
832            || print_aliases
833            || match &rel.cte {
834                Some(cte) => cte.name != refname,
835                None if rel.json_table().is_some() => false,
836                None if rel.oid == 0 => true,
837                None => {
838                    reg::class_name(rel.oid, self.session).is_none_or(|(name, _)| name != refname)
839                }
840            };
841        if show {
842            self.buf.push(' ');
843            self.buf.push_str(&quote_identifier(&refname));
844        }
845        if coldef {
846            self.coldef(&columns, &rel.columns)?;
847        } else if print_aliases && !columns.is_empty() {
848            // `get_column_alias_list` leaves out a dropped column.
849            let names: Vec<String> =
850                columns.iter().filter(|c| !c.is_empty()).map(|c| quote_identifier(c)).collect();
851            self.buf.push_str(&format!("({})", names.join(", ")));
852        }
853        // `TABLESAMPLE` goes after the alias.
854        if let Some(sample) = &rel.tablesample {
855            self.tablesample(sample)?;
856        }
857        Ok(())
858    }
859
860    /// `get_tablesample_def`: ` TABLESAMPLE method (args)`, then `REPEATABLE (seed)` when the query gives a seed.
861    fn tablesample(&mut self, sample: &TableSample) -> Result<()> {
862        let proc = builtin::proc_by_oid(sample.handler).ok_or_else(|| {
863            Error::internal(format!("cache lookup failed for function {}", sample.handler))
864        })?;
865        let name = if reg::function_visible(proc, self.session) {
866            quote_identifier(proc.name)
867        } else {
868            reg::qualified(reg::namespace_name(proc.namespace, self.session), proc.name)
869        };
870        self.buf.push_str(&format!(" TABLESAMPLE {name} ("));
871        for (i, arg) in sample.args.iter().enumerate() {
872            if i > 0 {
873                self.buf.push_str(", ");
874            }
875            self.expr(arg, false)?;
876        }
877        self.buf.push(')');
878        if let Some(seed) = &sample.repeatable {
879            self.buf.push_str(" REPEATABLE (");
880            self.expr(seed, false)?;
881            self.buf.push(')');
882        }
883        Ok(())
884    }
885
886    /// The calls of a function in `FROM`. The result is true when the column definition list of the one call goes after the alias.
887    fn function_item(&mut self, function: &FromFunction, columns: &[Column]) -> Result<bool> {
888        let has_coldef = |i: usize| function.coldefs.get(i).copied().unwrap_or(false);
889        let mut coldef = false;
890        if let [(call, _)] = function.calls.as_slice()
891            && (!has_coldef(0) || !function.ordinality)
892        {
893            self.funccall(call)?;
894            coldef = has_coldef(0);
895        } else if function.calls.iter().enumerate().all(|(i, (call, _))| {
896            !has_coldef(i) && matches!(&call.kind, ExprKind::Func(f) if f.oid == UNNEST)
897        }) {
898            self.buf.push_str("UNNEST(");
899            let mut first = true;
900            for (call, _) in &function.calls {
901                let ExprKind::Func(f) = &call.kind else { continue };
902                for arg in &f.args {
903                    if !first {
904                        self.buf.push_str(", ");
905                    }
906                    first = false;
907                    self.expr(arg, true)?;
908                }
909            }
910            self.buf.push(')');
911        } else {
912            self.buf.push_str("ROWS FROM(");
913            let mut at = 0;
914            for (i, (call, count)) in function.calls.iter().enumerate() {
915                if i > 0 {
916                    self.buf.push_str(", ");
917                }
918                self.funccall(call)?;
919                let part = columns.get(at..at + count).unwrap_or_default();
920                if has_coldef(i) {
921                    self.buf.push_str(" AS ");
922                    let names: Vec<String> = part.iter().map(|c| c.name.clone()).collect();
923                    self.coldef(&names, part)?;
924                }
925                at += count;
926            }
927            self.buf.push(')');
928        }
929        if function.ordinality {
930            self.buf.push_str(" WITH ORDINALITY");
931        }
932        Ok(coldef)
933    }
934
935    /// `get_rule_expr_funccall`: a call of a function in `FROM`, or `CAST(... AS type)` for an expression that the syntax of `FROM` does not take as a call.
936    fn funccall(&mut self, e: &Expr) -> Result<()> {
937        if looks_like_function(e) {
938            return self.expr(e, true);
939        }
940        self.buf.push_str("CAST(");
941        self.expr(e, false)?;
942        let ty = reg::type_text(e.ty, Some(e.typmod), self.session)?;
943        self.buf.push_str(&format!(" AS {ty})"));
944        Ok(())
945    }
946
947    /// `get_from_clause_coldeflist`: the column definition list of a function, `(name type, ...)`.
948    fn coldef(&mut self, names: &[String], columns: &[Column]) -> Result<()> {
949        self.buf.push('(');
950        for (i, (name, column)) in names.iter().zip(columns).enumerate() {
951            if i > 0 {
952                self.buf.push_str(", ");
953            }
954            let ty = reg::type_text(column.ty, Some(column.typmod), self.session)?;
955            self.buf.push_str(&format!("{} {ty}", quote_identifier(name)));
956        }
957        self.buf.push(')');
958        Ok(())
959    }
960
961    /// A join of `FROM`, with the names of `USING` that the namespace chooses. A join with an alias is always in parentheses, and the alias and the names of the columns come after them.
962    fn join(&mut self, join: &Join, query: &Query) -> Result<()> {
963        let mut relations = Vec::new();
964        base_relations(&join.left, &mut relations);
965        base_relations(&join.right, &mut relations);
966        let space = self.namespaces.last().ok_or_else(|| Error::internal("no namespace"))?;
967        let k = space
968            .joins
969            .iter()
970            .position(|j| j.relations == relations)
971            .ok_or_else(|| Error::internal("a join with no names"))?;
972        let using = space.joins[k].using.clone();
973        let paren_right = self.paren
974            && !matches!(&join.right, FromItem::Relation(_))
975            && !matches!(&join.right, FromItem::Join(right) if right.alias.is_some());
976        let parens = !self.paren || join.alias.is_some();
977        if parens {
978            self.buf.push('(');
979        }
980        if let Some(space) = self.namespaces.last_mut() {
981            space.inside.push(k);
982        }
983        let done = self.join_body(join, query, paren_right, &using);
984        if let Some(space) = self.namespaces.last_mut() {
985            space.inside.pop();
986        }
987        done?;
988        if parens {
989            self.buf.push(')');
990        }
991        let space = self.namespaces.last().ok_or_else(|| Error::internal("no namespace"))?;
992        let names = &space.joins[k];
993        if let Some(name) = &names.name {
994            let mut text = format!(" {}", quote_identifier(name));
995            if names.print_aliases && !names.columns.is_empty() {
996                let columns: Vec<String> =
997                    names.columns.iter().map(|c| quote_identifier(c)).collect();
998                text.push_str(&format!("({})", columns.join(", ")));
999            }
1000            self.buf.push_str(&text);
1001        }
1002        Ok(())
1003    }
1004
1005    /// The two sides of a join and its condition.
1006    fn join_body(
1007        &mut self,
1008        join: &Join,
1009        query: &Query,
1010        paren_right: bool,
1011        using: &[String],
1012    ) -> Result<()> {
1013        self.range_item(&join.left, query)?;
1014        let word = match join.kind {
1015            JoinKind::Inner if join.on.is_some() => " JOIN ",
1016            JoinKind::Inner => " CROSS JOIN ",
1017            JoinKind::Left => " LEFT JOIN ",
1018            JoinKind::Full => " FULL JOIN ",
1019            JoinKind::Right => " RIGHT JOIN ",
1020            JoinKind::Semi | JoinKind::Anti | JoinKind::RightSemi | JoinKind::RightAnti => " JOIN ",
1021        };
1022        self.keyword(word, -INDENT_STD, INDENT_STD, INDENT_JOIN);
1023        if paren_right {
1024            self.buf.push('(');
1025        }
1026        self.range_item(&join.right, query)?;
1027        if paren_right {
1028            self.buf.push(')');
1029        }
1030        if !join.using.is_empty() {
1031            let names: Vec<String> = using.iter().map(|n| quote_identifier(n)).collect();
1032            self.buf.push_str(&format!(" USING ({})", names.join(", ")));
1033            if let Some(alias) = &join.using_alias {
1034                self.buf.push_str(&format!(" AS {}", quote_identifier(alias)));
1035            }
1036        } else if let Some(on) = &join.on {
1037            self.buf.push_str(" ON ");
1038            self.open();
1039            self.expr(on, false)?;
1040            self.close();
1041        } else if join.kind != JoinKind::Inner {
1042            self.buf.push_str(" ON TRUE");
1043        }
1044        Ok(())
1045    }
1046
1047    /// `get_setop_query` for the operation of the query.
1048    fn set_op(&mut self, op: &SetOp, query: &Query, result: Option<&[String]>) -> Result<()> {
1049        let paren_left =
1050            matches!(&op.left, SetTree::Op(left) if left.kind != op.kind || left.all != op.all);
1051        let mut sub = 0;
1052        if paren_left {
1053            self.buf.push('(');
1054            sub = INDENT_STD;
1055            self.keyword("", sub, 0, 0);
1056        }
1057        self.set_tree(&op.left, query, result)?;
1058        self.keyword(if paren_left { ") " } else { "" }, -sub, 0, 0);
1059        self.buf.push_str(match op.kind {
1060            SetKind::Union => "UNION ",
1061            SetKind::Intersect => "INTERSECT ",
1062            SetKind::Except => "EXCEPT ",
1063        });
1064        if op.all {
1065            self.buf.push_str("ALL ");
1066        }
1067        let paren_right = matches!(op.right, SetTree::Op(_));
1068        sub = 0;
1069        if paren_right {
1070            self.buf.push('(');
1071            sub = INDENT_STD;
1072        }
1073        self.keyword("", sub, 0, 0);
1074        let saved = std::mem::replace(&mut self.names_visible, false);
1075        self.set_tree(&op.right, query, result)?;
1076        self.names_visible = saved;
1077        self.indent -= sub;
1078        if paren_right {
1079            self.keyword(")", 0, 0, 0);
1080        }
1081        Ok(())
1082    }
1083
1084    /// `get_setop_query` for a part of the operation: a `SELECT`, in parentheses when it has `ORDER BY`, `OFFSET`, `LIMIT` or an operation, or another operation.
1085    fn set_tree(&mut self, tree: &SetTree, query: &Query, result: Option<&[String]>) -> Result<()> {
1086        let index = match tree {
1087            SetTree::Op(op) => return self.set_op(op, query, result),
1088            SetTree::Leaf(index) => *index,
1089        };
1090        let sub = query
1091            .relations
1092            .get(index)
1093            .and_then(|r| r.subquery.as_deref())
1094            .ok_or_else(|| Error::internal("a part of a set operation with no query"))?;
1095        let paren = !sub.sort.is_empty()
1096            || sub.offset.is_some()
1097            || sub.limit.is_some()
1098            || sub.set_op.is_some();
1099        // The analyzer casts the columns of each `SELECT` to the types of the operation in place, but PostgreSQL keeps the `SELECT` as the query gives it and casts the rows of the operation.
1100        let mut sub = sub.clone();
1101        for target in &mut sub.targets {
1102            target.expr = target.expr.strip_implicit().clone();
1103        }
1104        if paren {
1105            self.buf.push('(');
1106        }
1107        self.query_def(&sub, result, self.names_visible, self.indent)?;
1108        if paren {
1109            self.buf.push(')');
1110        }
1111        Ok(())
1112    }
1113
1114    /// `get_rule_orderby`: the items of `ORDER BY`, each with its direction and the place of the nulls when they are not the default.
1115    fn order_by(&mut self, items: &[SortGroup], exprs: &[&Expr], force: bool) -> Result<()> {
1116        for (i, item) in items.iter().enumerate() {
1117            if i > 0 {
1118                self.buf.push_str(", ");
1119            }
1120            let e = exprs
1121                .get(item.target)
1122                .ok_or_else(|| Error::internal("an item of ORDER BY with no expression"))?;
1123            self.sort_group(e, item.target + 1, force)?;
1124            let (lt, gt) = sort_operators(e.ty);
1125            if item.operator == lt {
1126                if item.nulls_first {
1127                    self.buf.push_str(" NULLS FIRST");
1128                }
1129            } else if item.operator == gt {
1130                self.buf.push_str(" DESC");
1131                if !item.nulls_first {
1132                    self.buf.push_str(" NULLS LAST");
1133                }
1134            } else {
1135                let op = builtin::operator_by_oid(item.operator).ok_or_else(|| {
1136                    Error::internal(format!("cache lookup failed for operator {}", item.operator))
1137                })?;
1138                self.buf.push_str(&format!(" USING {}", op.name));
1139                self.buf.push_str(if item.nulls_first { " NULLS FIRST" } else { " NULLS LAST" });
1140            }
1141        }
1142        Ok(())
1143    }
1144
1145    /// `get_rule_sortgroupclause`: an item of `ORDER BY`, `GROUP BY` or `DISTINCT ON`. `force` shows the number of the column, for the `ORDER BY` of a set operation.
1146    fn sort_group(&mut self, e: &Expr, number: usize, force: bool) -> Result<()> {
1147        if force {
1148            self.buf.push_str(&number.to_string());
1149            return Ok(());
1150        }
1151        if self.merged_name(e).is_some() {
1152            return self.expr(e, true);
1153        }
1154        match &e.kind {
1155            ExprKind::Const(value) => self.constant(e, value, 1),
1156            ExprKind::Var(var) if var.attnum != 0 => self.variable(var, true).map(|_| ()),
1157            _ => {
1158                let paren = self.paren
1159                    || matches!(&e.kind, ExprKind::Func(f) if !matches!(f.form, FuncForm::Operator(_)))
1160                    || matches!(
1161                        e.kind,
1162                        ExprKind::Agg(_) | ExprKind::Window(_) | ExprKind::JsonCtor(_)
1163                    );
1164                if paren {
1165                    self.buf.push('(');
1166                }
1167                self.expr(e, true)?;
1168                if paren {
1169                    self.buf.push(')');
1170                }
1171                Ok(())
1172            }
1173        }
1174    }
1175
1176    /// `get_rule_groupingset`: a grouping set of `GROUP BY`. A simple set with one item has no parentheses when `omit_parens` is true.
1177    fn grouping_set(&mut self, query: &Query, set: &GroupingSet, omit_parens: bool) -> Result<()> {
1178        let (open, content, omit_child) = match set {
1179            GroupingSet::Empty => {
1180                self.buf.push_str("()");
1181                return Ok(());
1182            }
1183            GroupingSet::Simple(items) => {
1184                let parens = !omit_parens || items.len() != 1;
1185                if parens {
1186                    self.buf.push('(');
1187                }
1188                for (i, &target) in items.iter().enumerate() {
1189                    if i > 0 {
1190                        self.buf.push_str(", ");
1191                    }
1192                    let e = query
1193                        .targets
1194                        .get(target)
1195                        .map(|t| &t.expr)
1196                        .ok_or_else(|| Error::internal("a grouping set item has no target"))?;
1197                    self.sort_group(e, target + 1, false)?;
1198                }
1199                if parens {
1200                    self.buf.push(')');
1201                }
1202                return Ok(());
1203            }
1204            GroupingSet::Rollup(content) => ("ROLLUP(", content, true),
1205            GroupingSet::Cube(content) => ("CUBE(", content, true),
1206            GroupingSet::Sets(content) => ("GROUPING SETS (", content, false),
1207        };
1208        self.buf.push_str(open);
1209        for (i, child) in content.iter().enumerate() {
1210            if i > 0 {
1211                self.buf.push_str(", ");
1212            }
1213            self.grouping_set(query, child, omit_child)?;
1214        }
1215        self.buf.push(')');
1216        Ok(())
1217    }
1218
1219    /// `get_agg_expr`: a call of an aggregate function, with `DISTINCT`, `ORDER BY`, `WITHIN GROUP` and `FILTER`.
1220    pub(super) fn aggregate(&mut self, agg: &Aggref) -> Result<()> {
1221        self.aggregate_as(agg, None)
1222    }
1223
1224    /// `get_agg_expr_helper`: a call of an aggregate function. `json` has the name, the options and the kind of a SQL/JSON aggregate, where `JSON_OBJECTAGG` puts ` : ` between its two arguments.
1225    pub(super) fn aggregate_as(
1226        &mut self,
1227        agg: &Aggref,
1228        json: Option<(&str, &str, bool)>,
1229    ) -> Result<()> {
1230        let proc = builtin::proc_by_oid(agg.oid).ok_or_else(|| {
1231            Error::internal(format!("cache lookup failed for function {}", agg.oid))
1232        })?;
1233        match json {
1234            Some((name, _, _)) => self.buf.push_str(name),
1235            None => self.buf.push_str(&quote_identifier(proc.name)),
1236        }
1237        self.buf.push('(');
1238        if !agg.distinct.is_empty() {
1239            self.buf.push_str("DISTINCT ");
1240        }
1241        if agg.kind != b'n' {
1242            // An ordered-set aggregate has no `*` and no `VARIADIC`.
1243            for (i, arg) in agg.direct.iter().enumerate() {
1244                if i > 0 {
1245                    self.buf.push_str(", ");
1246                }
1247                self.expr(arg, true)?;
1248            }
1249            self.buf.push_str(") WITHIN GROUP (ORDER BY ");
1250            let exprs: Vec<&Expr> = agg.args.iter().collect();
1251            self.order_by(&agg.order, &exprs, false)?;
1252        } else if agg.star {
1253            self.buf.push('*');
1254        } else {
1255            let variadic = agg.variadic && proc.variadic != 0;
1256            let object = matches!(json, Some((_, _, true)));
1257            for (i, arg) in agg.args.iter().take(agg.nargs).enumerate() {
1258                if object && i > 1 {
1259                    break;
1260                }
1261                if i > 0 {
1262                    self.buf.push_str(if object { " : " } else { ", " });
1263                }
1264                if variadic && i + 1 == agg.nargs {
1265                    self.buf.push_str("VARIADIC ");
1266                }
1267                self.expr(arg, true)?;
1268            }
1269        }
1270        if agg.kind == b'n' && !agg.order.is_empty() {
1271            self.buf.push_str(" ORDER BY ");
1272            let exprs: Vec<&Expr> = agg.args.iter().collect();
1273            self.order_by(&agg.order, &exprs, false)?;
1274        }
1275        if let Some((_, options, _)) = json {
1276            self.buf.push_str(options);
1277        }
1278        if let Some(filter) = &agg.filter {
1279            self.buf.push_str(") FILTER (WHERE ");
1280            self.expr(filter, false)?;
1281        }
1282        self.buf.push(')');
1283        Ok(())
1284    }
1285
1286    /// `get_json_constructor` for `JSON_ARRAY` with a subquery. The subquery is the subquery in `FROM` of the query of `SELECT JSON_ARRAYAGG` in [`JsonCtor::func`].
1287    pub(super) fn json_array_query(&mut self, c: &JsonCtor) -> Result<()> {
1288        let wrapper = match c.func.as_ref().map(|f| &f.kind) {
1289            Some(ExprKind::Coalesce(args)) => match args.first().map(|a| &a.kind) {
1290                Some(ExprKind::SubLink(sub)) => Some(&sub.query),
1291                _ => None,
1292            },
1293            _ => None,
1294        };
1295        let Some(wrapper) = wrapper else {
1296            return Err(Error::internal("JSON_ARRAY with a subquery and no COALESCE"));
1297        };
1298        let Some(query) = wrapper.relations.first().and_then(|r| r.subquery.as_deref()) else {
1299            return Err(Error::internal("JSON_ARRAY with no subquery"));
1300        };
1301        self.buf.push_str("JSON_ARRAY(");
1302        // The subquery is one level below the query of `SELECT JSON_ARRAYAGG`, whose names the subquery does not see.
1303        let names = vec![String::new(); wrapper.relations.len()];
1304        self.namespaces.push(Namespace { names, ..Default::default() });
1305        let done = self.query_def(query, None, false, self.indent);
1306        self.namespaces.pop();
1307        done?;
1308        json_format(c.format, &mut self.buf);
1309        self.json_ctor_options(c)?;
1310        self.buf.push(')');
1311        Ok(())
1312    }
1313
1314    /// `get_sublink_expr`: a subquery in an expression.
1315    pub(super) fn sublink(&mut self, sub: &SubLink) -> Result<()> {
1316        self.buf.push_str(if sub.kind == SubLinkKind::Array { "ARRAY(" } else { "(" });
1317        let mut opname = "";
1318        if let Some(test) = &sub.test {
1319            // One operator, the operators of `=` or `<>` for a row on the left, or the operators of a comparison of rows.
1320            let (ops, row) = match &test.kind {
1321                ExprKind::Bool(_, ops) => (ops.as_slice(), true),
1322                ExprKind::RowCompare(rc) => (rc.ops.as_slice(), true),
1323                _ => (std::slice::from_ref(test), false),
1324            };
1325            if row {
1326                self.buf.push('(');
1327            }
1328            for (i, op) in ops.iter().enumerate() {
1329                let ExprKind::Func(Func { form: FuncForm::Operator(opno), args, .. }) = &op.kind
1330                else {
1331                    return Err(not_yet("a deparse of a subquery with this test"));
1332                };
1333                if i > 0 {
1334                    self.buf.push_str(", ");
1335                }
1336                let left =
1337                    args.first().ok_or_else(|| Error::internal("a test with no left argument"))?;
1338                self.expr(left, true)?;
1339                if i == 0 {
1340                    opname =
1341                        builtin::operator_by_oid(*opno).map(|op| op.name).ok_or_else(|| {
1342                            Error::internal(format!("cache lookup failed for operator {opno}"))
1343                        })?;
1344                }
1345            }
1346            if row {
1347                self.buf.push(')');
1348            }
1349        }
1350        let paren = match sub.kind {
1351            SubLinkKind::Exists => {
1352                self.buf.push_str("EXISTS ");
1353                true
1354            }
1355            SubLinkKind::Any if opname == "=" => {
1356                self.buf.push_str(" IN ");
1357                true
1358            }
1359            SubLinkKind::Any => {
1360                self.buf.push_str(&format!(" {opname} ANY "));
1361                true
1362            }
1363            SubLinkKind::All => {
1364                self.buf.push_str(&format!(" {opname} ALL "));
1365                true
1366            }
1367            SubLinkKind::RowCompare => {
1368                self.buf.push_str(&format!(" {opname} "));
1369                true
1370            }
1371            SubLinkKind::Expr | SubLinkKind::Array | SubLinkKind::Multi { .. } => false,
1372        };
1373        if paren {
1374            self.buf.push('(');
1375        }
1376        self.query_def(&sub.query, None, false, self.indent)?;
1377        self.buf.push_str(if paren { "))" } else { ")" });
1378        Ok(())
1379    }
1380
1381    /// `get_func_sql_syntax`: a call in the special syntax of the SQL standard. The result is false for a function that has no special syntax, which then shows as a plain call.
1382    pub(super) fn sql_syntax(&mut self, e: &Expr, f: &Func) -> Result<bool> {
1383        let proc = builtin::proc_by_oid(f.oid).ok_or_else(|| {
1384            Error::internal(format!("cache lookup failed for function {}", f.oid))
1385        })?;
1386        let args = f.args.as_slice();
1387        let text = |at: usize| match args.get(at).map(|a| (&a.kind, a.ty)) {
1388            Some((ExprKind::Const(value), oid::TEXT)) => value.as_str().map(str::to_string),
1389            _ => None,
1390        };
1391        match (proc.name, args) {
1392            ("timezone", [zone, value]) => {
1393                self.buf.push('(');
1394                self.paren(value, false, e)?;
1395                self.buf.push_str(" AT TIME ZONE ");
1396                self.paren(zone, false, e)?;
1397                self.buf.push(')');
1398            }
1399            ("timezone", [value]) => {
1400                self.buf.push('(');
1401                self.paren(value, false, e)?;
1402                self.buf.push_str(" AT LOCAL)");
1403            }
1404            ("overlaps", [a, b, c, d]) => {
1405                self.buf.push_str("((");
1406                self.expr(a, false)?;
1407                self.buf.push_str(", ");
1408                self.expr(b, false)?;
1409                self.buf.push_str(") OVERLAPS (");
1410                self.expr(c, false)?;
1411                self.buf.push_str(", ");
1412                self.expr(d, false)?;
1413                self.buf.push_str("))");
1414            }
1415            ("extract", [_, value]) => {
1416                let Some(field) = text(0) else { return Ok(false) };
1417                self.buf.push_str(&format!("EXTRACT({} FROM ", quote_identifier(&field)));
1418                self.expr(value, false)?;
1419                self.buf.push(')');
1420            }
1421            ("is_normalized", [value, rest @ ..]) if rest.len() <= 1 => {
1422                self.buf.push('(');
1423                self.paren(value, false, e)?;
1424                self.buf.push_str(" IS");
1425                if !rest.is_empty() {
1426                    let Some(form) = text(1) else { return Ok(false) };
1427                    self.buf.push_str(&format!(" {form}"));
1428                }
1429                self.buf.push_str(" NORMALIZED)");
1430            }
1431            ("pg_collation_for", [value]) => {
1432                self.buf.push_str("COLLATION FOR (");
1433                self.expr(value, false)?;
1434                self.buf.push(')');
1435            }
1436            ("normalize", [value, rest @ ..]) if rest.len() <= 1 => {
1437                self.buf.push_str("NORMALIZE(");
1438                self.expr(value, false)?;
1439                if !rest.is_empty() {
1440                    let Some(form) = text(1) else { return Ok(false) };
1441                    self.buf.push_str(&format!(", {form}"));
1442                }
1443                self.buf.push(')');
1444            }
1445            ("overlay", [value, placing, from, rest @ ..]) if rest.len() <= 1 => {
1446                self.buf.push_str("OVERLAY(");
1447                self.expr(value, false)?;
1448                self.buf.push_str(" PLACING ");
1449                self.expr(placing, false)?;
1450                self.buf.push_str(" FROM ");
1451                self.expr(from, false)?;
1452                if let [count] = rest {
1453                    self.buf.push_str(" FOR ");
1454                    self.expr(count, false)?;
1455                }
1456                self.buf.push(')');
1457            }
1458            ("position", [value, part]) => {
1459                self.buf.push_str("POSITION((");
1460                self.expr(part, false)?;
1461                self.buf.push_str(") IN (");
1462                self.expr(value, false)?;
1463                self.buf.push_str("))");
1464            }
1465            ("substring", [value, from, rest @ ..])
1466                if rest.len() <= 1 && proc.argtypes.get(1) == Some(&oid::INT4) =>
1467            {
1468                self.buf.push_str("SUBSTRING(");
1469                self.expr(value, false)?;
1470                self.buf.push_str(" FROM ");
1471                self.expr(from, false)?;
1472                if let [count] = rest {
1473                    self.buf.push_str(" FOR ");
1474                    self.expr(count, false)?;
1475                }
1476                self.buf.push(')');
1477            }
1478            ("substring", [value, pattern, escape]) => {
1479                self.buf.push_str("SUBSTRING(");
1480                self.expr(value, false)?;
1481                self.buf.push_str(" SIMILAR ");
1482                self.expr(pattern, false)?;
1483                self.buf.push_str(" ESCAPE ");
1484                self.expr(escape, false)?;
1485                self.buf.push(')');
1486            }
1487            ("btrim" | "ltrim" | "rtrim", [value, rest @ ..]) if rest.len() <= 1 => {
1488                self.buf.push_str(match proc.name {
1489                    "btrim" => "TRIM(BOTH",
1490                    "ltrim" => "TRIM(LEADING",
1491                    _ => "TRIM(TRAILING",
1492                });
1493                if let [chars] = rest {
1494                    self.buf.push(' ');
1495                    self.expr(chars, false)?;
1496                }
1497                self.buf.push_str(" FROM ");
1498                self.expr(value, false)?;
1499                self.buf.push(')');
1500            }
1501            ("system_user", []) => self.buf.push_str("SYSTEM_USER"),
1502            _ => return Ok(false),
1503        }
1504        Ok(true)
1505    }
1506}
1507
1508/// The values and the names of the columns of `USING` of the joins with no alias in a part of `FROM` that are not columns of one side.
1509fn merged_columns(item: &FromItem, out: &mut Vec<(Expr, String)>) {
1510    let FromItem::Join(join) = item else { return };
1511    merged_columns(&join.left, out);
1512    merged_columns(&join.right, out);
1513    if join.alias.is_none() {
1514        for (value, name) in join.merged.iter().zip(&join.using) {
1515            if !matches!(value.kind, ExprKind::Var(_)) {
1516                out.push((value.clone(), name.clone()));
1517            }
1518        }
1519    }
1520}
1521
1522/// The number of joins in a part of `FROM`, which `get_query_def` counts as entries of the range table.
1523fn join_count(item: &FromItem) -> usize {
1524    match item {
1525        FromItem::Relation(_) => 0,
1526        FromItem::Join(join) => 1 + join_count(&join.left) + join_count(&join.right),
1527    }
1528}
1529
1530/// The expression of an item of `ORDER BY`, `GROUP BY` or `DISTINCT ON`.
1531fn target_expr<'q>(query: &'q Query, item: &SortGroup) -> Result<&'q Expr> {
1532    query
1533        .targets
1534        .get(item.target)
1535        .map(|t| &t.expr)
1536        .ok_or_else(|| Error::internal("an item of a clause with no target"))
1537}
1538
1539/// The relations of a part of `FROM`, from left to right.
1540fn base_relations(item: &FromItem, out: &mut Vec<usize>) {
1541    match item {
1542        FromItem::Relation(i) => out.push(*i),
1543        FromItem::Join(join) => {
1544            base_relations(&join.left, out);
1545            base_relations(&join.right, out);
1546        }
1547    }
1548}
1549
1550/// A part of `FROM` as an entry of the range table: a relation by its index, or a join by its index in the joins of the query.
1551#[derive(Clone, Copy, Debug)]
1552enum Slot {
1553    Relation(usize),
1554    Join(usize),
1555}
1556
1557/// A join of `FROM` with its two sides and the relations in it.
1558#[derive(Debug)]
1559struct JoinInfo<'q> {
1560    join: &'q Join,
1561    left: Slot,
1562    right: Slot,
1563    relations: Vec<usize>,
1564}
1565
1566/// Adds the joins of a part of `FROM` to `joins`, an outer join before the joins in it, and adds the parts to `order` in the order of the range table, where a join comes after its two sides. The result is the slot of the part.
1567fn walk_from<'q>(item: &'q FromItem, joins: &mut Vec<JoinInfo<'q>>, order: &mut Vec<Slot>) -> Slot {
1568    let join = match item {
1569        FromItem::Relation(i) => {
1570            order.push(Slot::Relation(*i));
1571            return Slot::Relation(*i);
1572        }
1573        FromItem::Join(join) => join,
1574    };
1575    let k = joins.len();
1576    let (left, right) = (Slot::Relation(0), Slot::Relation(0));
1577    joins.push(JoinInfo { join, left, right, relations: Vec::new() });
1578    let left = walk_from(&join.left, joins, order);
1579    let right = walk_from(&join.right, joins, order);
1580    let mut relations = Vec::new();
1581    for side in [left, right] {
1582        match side {
1583            Slot::Relation(i) => relations.push(i),
1584            Slot::Join(j) => relations.extend_from_slice(&joins[j].relations),
1585        }
1586    }
1587    joins[k] = JoinInfo { join, left, right, relations };
1588    order.push(Slot::Join(k));
1589    Slot::Join(k)
1590}
1591
1592/// The name, or the name with `_1`, `_2` and so on when another relation of the query or of a query outside it has the name, as `set_rtable_names` chooses it.
1593pub(super) fn unique_name(base: String, used: &mut HashMap<String, u32>) -> String {
1594    let Some(mut counter) = used.get(&base).copied() else {
1595        used.insert(base.clone(), 0);
1596        return base;
1597    };
1598    let name = loop {
1599        counter += 1;
1600        let name = format!("{base}_{counter}");
1601        if !used.contains_key(&name) {
1602            break name;
1603        }
1604    };
1605    used.insert(base, counter);
1606    used.insert(name.clone(), 0);
1607    name
1608}
1609
1610/// The names of the columns of the relations and the joins of a query while the deparse chooses them, as `colnames` and `parentUsing` of each `deparse_columns` and `using_names` of `deparse_namespace`. `None` is a column with no name yet.
1611#[derive(Debug)]
1612struct ColumnNames {
1613    relations: Vec<Vec<Option<String>>>,
1614    relation_parents: Vec<Vec<String>>,
1615    joins: Vec<Vec<Option<String>>>,
1616    join_parents: Vec<Vec<String>>,
1617    /// `usingNames` of each join.
1618    join_using: Vec<Vec<String>>,
1619    /// `using_names`: the names of `USING` that must be unique in the query.
1620    using: Vec<String>,
1621    /// `unique_using`: true when a join with no alias has a column of `USING` that is not a column of one side, as `has_dangerous_join_using` finds.
1622    unique_using: bool,
1623}
1624
1625impl ColumnNames {
1626    fn names(&self, slot: Slot) -> Option<&Vec<Option<String>>> {
1627        match slot {
1628            Slot::Relation(i) => self.relations.get(i),
1629            Slot::Join(k) => self.joins.get(k),
1630        }
1631    }
1632
1633    /// Gives a name to the column with this number from 1 of a part of `FROM`, as a join pushes the names of its columns down to its sides. 0 is no column.
1634    fn push(&mut self, slot: Slot, number: usize, name: &str) {
1635        let names = match slot {
1636            Slot::Relation(i) => self.relations.get_mut(i),
1637            Slot::Join(k) => self.joins.get_mut(k),
1638        };
1639        if let Some(names) = names
1640            && number > 0
1641        {
1642            if names.len() < number {
1643                names.resize(number, None);
1644            }
1645            names[number - 1] = Some(name.to_string());
1646        }
1647    }
1648
1649    /// `make_colname_unique` and `colname_is_unique`: the name, or the name with `_1`, `_2` and so on when another column of the part of `FROM`, a column of `USING` of a join above it, or a name of `USING` that must be unique has it.
1650    fn unique(&self, name: &str, slot: Slot) -> String {
1651        let names = self.names(slot).map(Vec::as_slice).unwrap_or_default();
1652        let parents = match slot {
1653            Slot::Relation(i) => self.relation_parents.get(i),
1654            Slot::Join(k) => self.join_parents.get(k),
1655        };
1656        let parents = parents.map(Vec::as_slice).unwrap_or_default();
1657        let taken = |n: &str| {
1658            names.iter().flatten().any(|t| t == n)
1659                || parents.iter().any(|t| t == n)
1660                || self.using.iter().any(|t| t == n)
1661        };
1662        if !taken(name) {
1663            return name.to_string();
1664        }
1665        (1..).map(|i| format!("{name}_{i}")).find(|n| !taken(n)).unwrap_or_default()
1666    }
1667
1668    /// `set_using_names`: the names of the columns of `USING` of a join and of the joins in it. A join pushes these names down to the columns of its sides, and a join with no alias also pushes down the names that a join above it gives.
1669    fn using_names(&mut self, joins: &[JoinInfo<'_>], k: usize, parent: &[String]) {
1670        let Some(info) = joins.get(k) else { return };
1671        let join = info.join;
1672        if join.alias.is_none() {
1673            let pushed = self.joins.get(k).cloned().unwrap_or_default();
1674            for (i, name) in pushed.iter().enumerate() {
1675                let Some(name) = name else { continue };
1676                let (l, r) = join.sources.get(i).copied().unwrap_or_default();
1677                self.push(info.left, l, name);
1678                self.push(info.right, r, name);
1679            }
1680        }
1681        let mut parent = parent.to_vec();
1682        let mut using = Vec::with_capacity(join.using.len());
1683        for (i, written) in join.using.iter().enumerate() {
1684            let pushed = self.joins.get(k).and_then(|n| n.get(i)).cloned().flatten();
1685            let name = match pushed {
1686                Some(name) => name,
1687                None => {
1688                    // A name that the alias of the join gives is better than the name in `USING`.
1689                    let wanted = match &join.alias {
1690                        Some(_) => join.aliases.get(i).unwrap_or(written),
1691                        None => written,
1692                    };
1693                    let name = self.unique(wanted, Slot::Join(k));
1694                    if self.unique_using {
1695                        self.using.push(name.clone());
1696                    }
1697                    self.push(Slot::Join(k), i + 1, &name);
1698                    name
1699                }
1700            };
1701            let (l, r) = join.sources.get(i).copied().unwrap_or_default();
1702            self.push(info.left, l, &name);
1703            self.push(info.right, r, &name);
1704            parent.push(name.clone());
1705            using.push(name);
1706        }
1707        if let Some(slot) = self.join_using.get_mut(k) {
1708            *slot = using;
1709        }
1710        for side in [info.left, info.right] {
1711            match side {
1712                Slot::Relation(i) => {
1713                    if let Some(slot) = self.relation_parents.get_mut(i) {
1714                        slot.clone_from(&parent);
1715                    }
1716                }
1717                Slot::Join(j) => {
1718                    if let Some(slot) = self.join_parents.get_mut(j) {
1719                        slot.clone_from(&parent);
1720                    }
1721                    self.using_names(joins, j, &parent);
1722                }
1723            }
1724        }
1725    }
1726
1727    /// `set_join_column_names`: the names of the columns of a join that are not columns of `USING`, after the names of its sides. A join with no alias takes the names of its sides. The result is `printaliases`: true for a join with an alias when a name is not the name of the column of its side.
1728    fn join_columns(&mut self, joins: &[JoinInfo<'_>], k: usize) -> bool {
1729        let Some(info) = joins.get(k) else { return false };
1730        let join = info.join;
1731        let mut changed = false;
1732        for i in join.using.len()..join.columns.len() {
1733            let (l, r) = join.sources.get(i).copied().unwrap_or_default();
1734            let (side, number) = if l > 0 { (info.left, l) } else { (info.right, r) };
1735            // The number of a column of a table counts the columns that are not dropped.
1736            let names = self.names(side).map(Vec::as_slice).unwrap_or_default();
1737            let real = match side {
1738                Slot::Relation(_) => {
1739                    names.iter().filter(|n| n.as_deref() != Some("")).nth(number.wrapping_sub(1))
1740                }
1741                Slot::Join(_) => names.get(number.wrapping_sub(1)),
1742            };
1743            let real = real.cloned().flatten();
1744            let Some(real) = real else { continue };
1745            let assigned = self.joins.get(k).and_then(|n| n.get(i)).cloned().flatten();
1746            let name = match (&join.alias, assigned) {
1747                (None, _) => real.clone(),
1748                (Some(_), Some(name)) => name,
1749                (Some(_), None) => {
1750                    let wanted = join.aliases.get(i).unwrap_or(&real);
1751                    self.unique(wanted, Slot::Join(k))
1752                }
1753            };
1754            changed |= name != real;
1755            self.push(Slot::Join(k), i + 1, &name);
1756        }
1757        join.alias.is_some() && changed
1758    }
1759}
1760
1761/// `get_simple_values_rte`: the rows of the query when it is a plain `VALUES` list whose columns keep their names.
1762fn simple_values<'q>(query: &'q Query, result: Option<&[String]>) -> Option<&'q [Vec<Expr>]> {
1763    let [rel] = query.relations.as_slice() else { return None };
1764    let rows = rel.values.as_deref()?;
1765    if query.targets.len() != rel.columns.len() {
1766        return None;
1767    }
1768    for (i, (target, column)) in query.targets.iter().zip(&rel.columns).enumerate() {
1769        let name = result.and_then(|r| r.get(i)).unwrap_or(&target.name);
1770        if target.junk || *name != column.name {
1771            return None;
1772        }
1773    }
1774    Some(rows)
1775}
1776
1777/// `contain_vars_of_level`: true when the expression has a column of the query at this level above it, also in a subquery.
1778fn refers_to(e: &Expr, level: usize) -> bool {
1779    match &e.kind {
1780        ExprKind::Var(var) => var.levels_up == level,
1781        ExprKind::SubLink(sub) => {
1782            sub.test.as_ref().is_some_and(|t| refers_to(t, level))
1783                || sub.query.exprs().into_iter().any(|x| refers_to(x, level + 1))
1784        }
1785        _ => e.children().into_iter().any(|c| refers_to(c, level)),
1786    }
1787}
1788
1789/// `pg_get_viewdef_worker`: the query of the view and a `;`, or null when the relation is not a view.
1790fn viewdef(oid: u32, paren: bool, wrap: i32, session: &dyn Session) -> Result<Value> {
1791    let env = reg::SessionEnv(session);
1792    let Some(query) = rupg_analyze::view_query(&env, oid)? else { return Ok(Value::Null) };
1793    let rel = session
1794        .catalog()
1795        .and_then(|c| c.relation(oid))
1796        .ok_or_else(|| Error::internal(format!("cache lookup failed for relation {oid}")))?;
1797    let result: Vec<String> = rel.columns.iter().map(|c| c.name.clone()).collect();
1798    let mut d = Deparser::new(session, paren, wrap);
1799    d.query_def(&query, Some(&result), true, 0)?;
1800    d.buf.push(';');
1801    Ok(Value::text(d.buf))
1802}
1803
1804/// The text of a `CREATE VIEW` statement that makes the view `name` again with the query and the names of its columns, as `pg_get_viewdef_worker` gives the query. The catalog keeps the text of a view, and the text names the objects that the query reads, so `ALTER ... RENAME` writes the text again from the query of the old names.
1805///
1806/// # Errors
1807///
1808/// The errors of the deparse.
1809pub fn view_statement(
1810    query: &Query,
1811    name: &str,
1812    columns: &[String],
1813    session: &dyn Session,
1814) -> Result<String> {
1815    let mut d = Deparser::new(session, false, 0);
1816    d.query_def(query, Some(columns), true, 0)?;
1817    Ok(format!("CREATE VIEW {} AS {}", quote_identifier(name), d.buf))
1818}
1819
1820/// The pretty flags and the wrap column of a call from its second argument: none for `pg_get_viewdef(oid)`, a `boolean` for `pg_get_viewdef(oid, bool)`, and the wrap column for `pg_get_viewdef(oid, int4)`, which also sets `PRETTYFLAG_PAREN`.
1821fn flags(args: &[Value]) -> Result<(bool, i32)> {
1822    match args.get(1) {
1823        None => Ok((false, 0)),
1824        Some(Value::Bool(pretty)) => Ok((*pretty, 0)),
1825        Some(value) => {
1826            let wrap = value.as_i64().ok_or_else(bad_value)?;
1827            Ok((true, i32::try_from(wrap).map_err(|_| bad_value())?))
1828        }
1829    }
1830}
1831
1832/// `pg_get_viewdef(oid)`, `pg_get_viewdef(oid, bool)` and `pg_get_viewdef(oid, int4)`.
1833pub(super) fn get_viewdef(call: &Call<'_>, args: &[Value]) -> Result<Value> {
1834    let oid = args.first().and_then(Value::as_oid).ok_or_else(bad_value)?;
1835    let (paren, wrap) = flags(args)?;
1836    viewdef(oid, paren, wrap, call.session)
1837}
1838
1839/// `pg_get_viewdef(text)` and `pg_get_viewdef(text, bool)`: the view of a name that `search_path` finds.
1840pub(super) fn get_viewdef_name(call: &Call<'_>, args: &[Value]) -> Result<Value> {
1841    let text = args.first().and_then(Value::as_str).ok_or_else(bad_value)?;
1842    let names = qualified_name_list(text).map_err(type_error)?;
1843    let oid = reg::relation_oid(&names, call.session)?;
1844    let (paren, wrap) = flags(args)?;
1845    viewdef(oid, paren, wrap, call.session)
1846}
1847
1848/// `pg_get_ruledef(oid)` and `pg_get_ruledef(oid, bool)`: the `CREATE RULE` statement of a rule, as `make_ruledef` makes it, or null when no rule has the OID. The `_RETURN` rule of a view is `ON SELECT DO INSTEAD` with the query of the view.
1849pub(super) fn get_ruledef(call: &Call<'_>, args: &[Value]) -> Result<Value> {
1850    let oid = args.first().and_then(Value::as_oid).ok_or_else(bad_value)?;
1851    let pretty = pretty_arg(args, 1)?;
1852    let Some(catalog) = call.session.catalog() else { return Ok(Value::Null) };
1853    if let Some(rule) = catalog.rule(oid) {
1854        return ruledef(rule, pretty, call.session).map(Value::Text);
1855    }
1856    let view = catalog.relations().find(|r| r.view.as_ref().is_some_and(|v| v.rule == oid));
1857    let Some(view) = view.map(|r| r.oid) else { return Ok(Value::Null) };
1858    let Value::Text(query) = viewdef(view, pretty, 0, call.session)? else {
1859        return Ok(Value::Null);
1860    };
1861    let name = if pretty {
1862        relation_name(view, call.session)?
1863    } else {
1864        qualified_relation_name(view, call.session)?
1865    };
1866    let rule = quote_identifier("_RETURN");
1867    Ok(Value::Text(format!("CREATE RULE {rule} AS\n    ON SELECT TO {name} DO INSTEAD {query}")))
1868}
1869
1870/// `make_ruledef` for a rule of `CREATE RULE`. The condition reads the names of the first action, and `DO INSTEAD NOTHING` has the query of `NOTHING` as its action.
1871fn ruledef(rule: &rupg_catalog::Rule, pretty: bool, session: &dyn Session) -> Result<String> {
1872    let env = reg::SessionEnv(session);
1873    let tree = rupg_analyze::rule_tree(&env, rule.oid)?
1874        .ok_or_else(|| Error::internal(format!("cache lookup failed for rule {}", rule.oid)))?;
1875    if tree.actions.iter().any(|a| a.write.is_some()) {
1876        return Err(not_yet("a deparse of a rule action INSERT, UPDATE or DELETE"));
1877    }
1878    let event = match rule.event {
1879        b'1' => "SELECT",
1880        b'2' => "UPDATE",
1881        b'3' => "INSERT",
1882        _ => "DELETE",
1883    };
1884    let name = if pretty {
1885        relation_name(rule.relation, session)?
1886    } else {
1887        qualified_relation_name(rule.relation, session)?
1888    };
1889    let mut d = Deparser::new(session, pretty, 0);
1890    d.buf = format!("CREATE RULE {} AS\n    ON {event} TO {name}", quote_identifier(&rule.name));
1891    if let Some(qual) = &tree.qual {
1892        d.buf.push_str("\n   WHERE ");
1893        let context = tree.actions.first().unwrap_or(&tree.base);
1894        let space = d.namespace(context);
1895        d.prefix = context.relations.len() != 1;
1896        d.indent = INDENT_STD;
1897        d.namespaces.push(space);
1898        d.expr(qual, false)?;
1899        d.namespaces.pop();
1900        d.indent = 0;
1901        d.prefix = false;
1902    }
1903    d.buf.push_str(" DO ");
1904    if rule.instead {
1905        d.buf.push_str("INSTEAD ");
1906    }
1907    match tree.actions.as_slice() {
1908        [] => d.buf.push_str("NOTHING;"),
1909        [action] => {
1910            d.query_def(action, None, true, 0)?;
1911            d.buf.push(';');
1912        }
1913        actions => {
1914            d.buf.push('(');
1915            for action in actions {
1916                d.query_def(action, None, true, 0)?;
1917                d.buf.push_str(";\n");
1918            }
1919            d.buf.push_str(");");
1920        }
1921    }
1922    Ok(d.buf)
1923}
1924
1925/// `pg_get_triggerdef(oid)` and `pg_get_triggerdef(oid, bool)`: the `CREATE TRIGGER` statement of a trigger, as `pg_get_triggerdef_worker` makes it, or null when no trigger has the OID.
1926pub(super) fn get_triggerdef(call: &Call<'_>, args: &[Value]) -> Result<Value> {
1927    let oid = args.first().and_then(Value::as_oid).ok_or_else(bad_value)?;
1928    let pretty = pretty_arg(args, 1)?;
1929    let session = call.session;
1930    let Some(trigger) = session.catalog().and_then(|c| c.trigger(oid)) else {
1931        return Ok(Value::Null);
1932    };
1933    let kind = trigger.kind;
1934    let constraint = if trigger.constraint != 0 { "CONSTRAINT " } else { "" };
1935    let mut d = Deparser::new(session, pretty, 0);
1936    d.buf = format!("CREATE {constraint}TRIGGER {} ", quote_identifier(&trigger.name));
1937    d.buf.push_str(if kind & TRIGGER_BEFORE != 0 {
1938        "BEFORE"
1939    } else if kind & TRIGGER_INSTEAD != 0 {
1940        "INSTEAD OF"
1941    } else {
1942        "AFTER"
1943    });
1944    let mut events = 0;
1945    let mut event = |d: &mut Deparser<'_>, name: &str| {
1946        d.buf.push_str(if events > 0 { " OR " } else { " " });
1947        d.buf.push_str(name);
1948        events += 1;
1949    };
1950    if kind & TRIGGER_INSERT != 0 {
1951        event(&mut d, "INSERT");
1952    }
1953    if kind & TRIGGER_DELETE != 0 {
1954        event(&mut d, "DELETE");
1955    }
1956    if kind & TRIGGER_UPDATE != 0 {
1957        event(&mut d, "UPDATE");
1958        if !trigger.columns.is_empty() {
1959            let names = column_names(trigger.relation, session).unwrap_or_default();
1960            let columns: Vec<String> = trigger
1961                .columns
1962                .iter()
1963                .map(|&n| {
1964                    let at = usize::try_from(n - 1).unwrap_or(usize::MAX);
1965                    names.get(at).map_or_else(String::new, |n| quote_identifier(n))
1966                })
1967                .collect();
1968            d.buf.push_str(" OF ");
1969            d.buf.push_str(&columns.join(", "));
1970        }
1971    }
1972    if kind & TRIGGER_TRUNCATE != 0 {
1973        event(&mut d, "TRUNCATE");
1974    }
1975    let name = if pretty {
1976        relation_name(trigger.relation, session)?
1977    } else {
1978        qualified_relation_name(trigger.relation, session)?
1979    };
1980    d.buf.push_str(&format!(" ON {name} "));
1981    if trigger.constraint != 0 {
1982        if trigger.constraint_relation != 0 {
1983            let from = relation_name(trigger.constraint_relation, session)?;
1984            d.buf.push_str(&format!("FROM {from} "));
1985        }
1986        if !trigger.deferrable {
1987            d.buf.push_str("NOT ");
1988        }
1989        d.buf.push_str("DEFERRABLE INITIALLY ");
1990        d.buf.push_str(if trigger.deferred { "DEFERRED " } else { "IMMEDIATE " });
1991    }
1992    if trigger.old_table.is_some() || trigger.new_table.is_some() {
1993        d.buf.push_str("REFERENCING ");
1994        if let Some(old) = &trigger.old_table {
1995            d.buf.push_str(&format!("OLD TABLE AS {} ", quote_identifier(old)));
1996        }
1997        if let Some(new) = &trigger.new_table {
1998            d.buf.push_str(&format!("NEW TABLE AS {} ", quote_identifier(new)));
1999        }
2000    }
2001    d.buf.push_str(if kind & TRIGGER_ROW != 0 { "FOR EACH ROW " } else { "FOR EACH STATEMENT " });
2002    let env = reg::SessionEnv(session);
2003    if let Some((base, qual)) = rupg_analyze::trigger_when(&env, oid)? {
2004        d.buf.push_str("WHEN (");
2005        let space = d.namespace(&base);
2006        d.prefix = true;
2007        d.indent = INDENT_STD;
2008        d.namespaces.push(space);
2009        d.expr(&qual, false)?;
2010        d.namespaces.pop();
2011        d.indent = 0;
2012        d.prefix = false;
2013        d.buf.push_str(") ");
2014    }
2015    let proc = builtin::proc_by_oid(trigger.function).ok_or_else(|| {
2016        Error::internal(format!("cache lookup failed for function {}", trigger.function))
2017    })?;
2018    let function = if reg::function_visible(proc, session) {
2019        quote_identifier(proc.name)
2020    } else {
2021        reg::qualified(reg::namespace_name(proc.namespace, session), proc.name)
2022    };
2023    // `simple_quote_literal` with `standard_conforming_strings` on doubles only the quote.
2024    let args: Vec<String> =
2025        trigger.args.iter().map(|a| format!("'{}'", a.replace('\'', "''"))).collect();
2026    d.buf.push_str(&format!("EXECUTE FUNCTION {function}({})", args.join(", ")));
2027    Ok(Value::text(d.buf))
2028}