LCOV - code coverage report
Current view: top level - dashql-core/src/formatter - mod.rs Coverage Total Hit
Test: DashQL 915828b Lines: 92.1 % 2293 2111
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : //! The SQL formatter.
       2              : //!
       3              : //! The formatter visits the AST in post-order and builds a document for every node in a
       4              : //! [`FormattingProgram`], so the documents of the children always exist when a parent is visited.
       5              : //! Nodes that cannot be formatted are rendered as `'<NODE_TYPE>'` placeholders and recorded as
       6              : //! unformattable. The statements are then rendered with the comments of the script in between.
       7              : //!
       8              : //! The output keeps the quirks listed in docs/design/core_quirks.md. The statement formatters live in
       9              : //! the submodules, one per statement kind.
      10              : 
      11              : mod comments;
      12              : mod create;
      13              : mod delete;
      14              : mod explain;
      15              : mod insert;
      16              : mod pgq;
      17              : pub mod program;
      18              : mod select;
      19              : 
      20              : pub use program::*;
      21              : 
      22              : use dashql_parser::attrs;
      23              : use dashql_buffers::formatting::{FormattingConfigT, FormattingDialect, FormattingMode};
      24              : use dashql_buffers::parser::{
      25              :     AttributeKey, CharacterType, ColumnConstraint, ConstraintAttribute, ExpressionOperator, ExtractTarget,
      26              :     GroupByItemType, IntervalType, JoinType, KeyActionCommand, KeyActionTrigger, KeyMatch, KnownFunction, Node,
      27              :     NodeType, NumericType, OrderDirection, OrderNullRule, RowLockingBlockBehavior, RowLockingStrength, SampleCountUnit,
      28              :     SubqueryQuantifier, SymbolSpan, TableConstraint, TempType, TrimDirection, WindowBoundDirection, WindowBoundMode,
      29              :     WindowRangeMode,
      30              : };
      31              : use dashql_parser::parser::context::resolve_text_span;
      32              : use dashql_parser::parser::ParsedScript;
      33              : use dashql_parser::scanner::ScannedScript;
      34              : use dashql_parser::span::TextSpan;
      35              : use std::cell::{Cell, RefCell};
      36              : 
      37              : type K = AttributeKey;
      38              : 
      39              : #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
      40              : pub enum FormattingAssociativity {
      41              :     Left,
      42              :     Right,
      43              :     #[default]
      44              :     NonAssoc,
      45              : }
      46              : 
      47              : use FormattingAssociativity as Associativity;
      48              : 
      49              : /// The formatting state of an AST node
      50              : #[derive(Clone, Copy, Debug, Default)]
      51              : pub struct FormattingNodeState {
      52              :     /// The operator precedence of an n-ary expression or its argument array, 0 if none
      53              :     pub precedence: usize,
      54              :     /// The operator associativity of an n-ary expression or its argument array
      55              :     pub associativity: FormattingAssociativity,
      56              :     /// Must the n-ary expression be parenthesized within its parent expression?
      57              :     pub needs_parentheses: bool,
      58              :     /// Is the node the root of a statement, or the statement of an EXPLAIN?
      59              :     pub is_statement_root: bool,
      60              :     /// The formatted document of the node
      61              :     pub reg: FmtReg,
      62              : }
      63              : 
      64        26980 : fn get_operator_precedence(op: ExpressionOperator) -> (usize, Associativity) {
      65              :     use ExpressionOperator as O;
      66        26980 :     match op {
      67          805 :         O::OR => (3, Associativity::Left),
      68         3332 :         O::AND => (4, Associativity::Left),
      69           93 :         O::NOT => (5, Associativity::Right),
      70              :         O::IS_NULL
      71              :         | O::NOT_NULL
      72              :         | O::IS_TRUE
      73              :         | O::IS_FALSE
      74              :         | O::IS_UNKNOWN
      75              :         | O::IS_DISTINCT_FROM
      76              :         | O::IS_OF
      77              :         | O::IS_NOT_TRUE
      78              :         | O::IS_NOT_FALSE
      79              :         | O::IS_NOT_UNKNOWN
      80              :         | O::IS_NOT_DISTINCT_FROM
      81              :         | O::IS_NOT_OF
      82              :         | O::EQUAL
      83              :         | O::NOT_EQUAL
      84              :         | O::GREATER_EQUAL
      85              :         | O::GREATER_THAN
      86              :         | O::LESS_EQUAL
      87        14603 :         | O::LESS_THAN => (6, Associativity::NonAssoc),
      88              :         O::BETWEEN_SYMMETRIC
      89              :         | O::BETWEEN_ASYMMETRIC
      90              :         | O::NOT_BETWEEN_SYMMETRIC
      91              :         | O::NOT_BETWEEN_ASYMMETRIC
      92              :         | O::IN
      93              :         | O::NOT_IN
      94              :         | O::GLOB
      95              :         | O::NOT_GLOB
      96              :         | O::LIKE
      97              :         | O::NOT_LIKE
      98              :         | O::ILIKE
      99              :         | O::NOT_ILIKE
     100              :         | O::SIMILAR_TO
     101              :         | O::NOT_SIMILAR_TO
     102         2847 :         | O::OVERLAPS => (7, Associativity::NonAssoc),
     103         2729 :         O::PLUS | O::MINUS => (12, Associativity::Left),
     104         2261 :         O::MULTIPLY | O::DIVIDE | O::MODULUS => (13, Associativity::Left),
     105           24 :         O::XOR => (14, Associativity::Left),
     106           12 :         O::AT_TIMEZONE => (15, Associativity::Left),
     107            9 :         O::COLLATE => (16, Associativity::Left),
     108          259 :         O::NEGATE => (17, Associativity::Right),
     109            0 :         O::TYPECAST => (20, Associativity::Left),
     110              :         // Unknown operators get precedence 0, non-associative (see docs/design/core_quirks.md)
     111            6 :         _ => (0, Associativity::NonAssoc),
     112              :     }
     113        26980 : }
     114              : 
     115              : /// Break before AND and OR, after every other operator
     116        23817 : fn breaks_before_operator(op: ExpressionOperator) -> bool {
     117        23817 :     matches!(op, ExpressionOperator::OR | ExpressionOperator::AND)
     118        23817 : }
     119              : 
     120        27097 : fn get_operator_text(op: ExpressionOperator) -> &'static str {
     121              :     use ExpressionOperator as O;
     122        27097 :     match op {
     123          259 :         O::NEGATE => "-",
     124           93 :         O::NOT => "not",
     125         1895 :         O::PLUS => "+",
     126          852 :         O::MINUS => "-",
     127         1376 :         O::MULTIPLY => "*",
     128          873 :         O::DIVIDE => "/",
     129           12 :         O::MODULUS => "%",
     130         3332 :         O::AND => "and",
     131          805 :         O::OR => "or",
     132              :         // The `^` of the grammar, the exponentiation of Hyper and PostgreSQL (`#` would be their bitwise xor)
     133           24 :         O::XOR => "^",
     134        12077 :         O::EQUAL => "=",
     135          159 :         O::NOT_EQUAL => "<>",
     136          315 :         O::LESS_THAN => "<",
     137         1113 :         O::GREATER_THAN => ">",
     138          489 :         O::LESS_EQUAL => "<=",
     139          222 :         O::GREATER_EQUAL => ">=",
     140          117 :         O::LIKE => "like",
     141           30 :         O::NOT_LIKE => "not like",
     142            9 :         O::ILIKE => "ilike",
     143            9 :         O::NOT_ILIKE => "not ilike",
     144            9 :         O::SIMILAR_TO => "similar to",
     145            6 :         O::NOT_SIMILAR_TO => "not similar to",
     146           12 :         O::OVERLAPS => "overlaps",
     147           12 :         O::GLOB => "glob",
     148           18 :         O::NOT_GLOB => "not glob",
     149          105 :         O::IS_NULL => "is null",
     150          102 :         O::NOT_NULL => "is not null",
     151            9 :         O::IS_TRUE => "is true",
     152            9 :         O::IS_FALSE => "is false",
     153            9 :         O::IS_UNKNOWN => "is unknown",
     154            9 :         O::IS_NOT_TRUE => "is not true",
     155            9 :         O::IS_NOT_FALSE => "is not false",
     156            9 :         O::IS_NOT_UNKNOWN => "is not unknown",
     157           15 :         O::IS_DISTINCT_FROM => "is distinct from",
     158           15 :         O::IS_NOT_DISTINCT_FROM => "is not distinct from",
     159         1086 :         O::IN => "in",
     160           18 :         O::NOT_IN => "not in",
     161         1482 :         O::BETWEEN_ASYMMETRIC => "between",
     162           21 :         O::BETWEEN_SYMMETRIC => "between symmetric",
     163           33 :         O::NOT_BETWEEN_ASYMMETRIC => "not between",
     164           21 :         O::NOT_BETWEEN_SYMMETRIC => "not between symmetric",
     165            9 :         O::COLLATE => "collate",
     166           12 :         O::AT_TIMEZONE => "at time zone",
     167            6 :         O::DEFAULT => "default",
     168            0 :         _ => "",
     169              :     }
     170        27097 : }
     171              : 
     172         2172 : fn get_known_function_text(function: KnownFunction) -> &'static str {
     173              :     use KnownFunction as F;
     174         2172 :     match function {
     175            3 :         F::COLLATION_FOR => "collation for",
     176            9 :         F::CURRENT_DATE => "current_date",
     177           24 :         F::CURRENT_TIME => "current_time",
     178           36 :         F::CURRENT_TIMESTAMP => "current_timestamp",
     179           18 :         F::LOCALTIME => "localtime",
     180           18 :         F::LOCALTIMESTAMP => "localtimestamp",
     181            9 :         F::CURRENT_ROLE => "current_role",
     182            9 :         F::CURRENT_USER => "current_user",
     183            9 :         F::SESSION_USER => "session_user",
     184            9 :         F::USER => "user",
     185            9 :         F::CURRENT_CATALOG => "current_catalog",
     186            9 :         F::CURRENT_SCHEMA => "current_schema",
     187         1119 :         F::CAST => "cast",
     188           81 :         F::EXTRACT => "extract",
     189           18 :         F::OVERLAY => "overlay",
     190           15 :         F::POSITION => "position",
     191          255 :         F::SUBSTRING => "substring",
     192           15 :         F::TREAT => "treat",
     193           81 :         F::TRIM => "trim",
     194           15 :         F::NULLIF => "nullif",
     195          402 :         F::COALESCE => "coalesce",
     196            9 :         F::TRY_CAST => "try_cast",
     197            0 :         _ => "",
     198              :     }
     199         2172 : }
     200              : 
     201              : /// The value of an enum node
     202        97097 : fn value_u8(node: &Node) -> u8 {
     203        97097 :     node.children_begin_or_value() as u8
     204        97097 : }
     205              : 
     206              : /// Is the node a true BOOL?
     207        30497 : fn is_true(node: Option<&Node>) -> bool {
     208        30497 :     node.is_some_and(|n| n.node_type() == NodeType::BOOL && n.children_begin_or_value() != 0)
     209        30497 : }
     210              : 
     211              : /// A part of the formatted script
     212              : #[derive(Clone, Copy, Debug)]
     213              : enum OutputPart {
     214              :     /// A parsed statement without errors, the index in the statements of the parsed script
     215              :     Statement(usize),
     216              :     /// A statement with syntax errors, the text span that is copied as written
     217              :     Damaged(TextSpan),
     218              : }
     219              : 
     220              : /// The SQL formatter
     221              : pub struct Formatter<'a> {
     222              :     /// The scanned script
     223              :     scanned: &'a ScannedScript,
     224              :     /// Emit executable literals instead of obfuscated literal markers?
     225              :     replace_obfuscated_literals: bool,
     226              :     /// The parsed script
     227              :     parsed: &'a ParsedScript,
     228              :     /// The AST nodes of the parsed script
     229              :     ast: &'a [Node],
     230              :     /// The formatting config of the current run
     231              :     config: FormattingConfigT,
     232              :     /// The document arena that holds the formatted nodes
     233              :     fmt: FormattingProgram<'a>,
     234              :     /// The formatting states, indexed by AST node id
     235              :     node_states: Vec<FormattingNodeState>,
     236              :     /// The ids of the nodes that were rendered as placeholders
     237              :     unformattable_nodes: RefCell<Vec<u32>>,
     238              :     /// Was a part of the script with syntax errors copied as written?
     239              :     copied_damaged_text: Cell<bool>,
     240              : }
     241              : 
     242              : impl<'a> Formatter<'a> {
     243         4146 :     pub fn new(parsed: &'a ParsedScript) -> Self {
     244         4146 :         let mut formatter = Self {
     245         4146 :             scanned: &parsed.scanned,
     246         4146 :             replace_obfuscated_literals: false,
     247         4146 :             parsed,
     248         4146 :             ast: &parsed.nodes,
     249         4146 :             config: FormattingConfigT::default(),
     250         4146 :             fmt: FormattingProgram::new(),
     251         4146 :             node_states: vec![FormattingNodeState::default(); parsed.nodes.len()],
     252         4146 :             unformattable_nodes: RefCell::new(Vec::new()),
     253         4146 :             copied_damaged_text: Cell::new(false),
     254         4146 :         };
     255         4146 :         formatter.mark_statement_roots();
     256         4146 :         formatter
     257         4146 :     }
     258              : 
     259              :     /// Emit executable literals instead of the obfuscated literal markers of Hyper
     260            6 :     pub fn replace_obfuscated_literals(&mut self) {
     261            6 :         self.replace_obfuscated_literals = true;
     262            6 :     }
     263              : 
     264         5330 :     pub fn estimate_formatted_size(&self) -> usize {
     265         5330 :         self.scanned.text.len() + 64
     266         5330 :     }
     267              : 
     268              :     /// The nodes that could not be formatted by the last call of `format` or `format_node_at`
     269          604 :     pub fn unformattable_nodes(&self) -> Vec<u32> {
     270          604 :         self.unformattable_nodes.borrow().clone()
     271          604 :     }
     272              : 
     273              :     /// Was everything formatted? Parts with syntax errors are copied as written and nodes that cannot be
     274              :     /// formatted are rendered as placeholders.
     275         1929 :     pub fn is_fully_formatted(&self) -> bool {
     276         1929 :         self.unformattable_nodes.borrow().is_empty() && !self.copied_damaged_text.get()
     277         1929 :     }
     278              : 
     279              :     /// Format the script
     280         5322 :     pub fn format(&mut self, config: &FormattingConfigT) -> String {
     281         5322 :         bytes_to_string(self.format_bytes(config))
     282         5322 :     }
     283              : 
     284              :     /// Format the script, the output may contain partial UTF-8 sequences where comments were wrapped
     285         5330 :     pub fn format_bytes(&mut self, config: &FormattingConfigT) -> Vec<u8> {
     286         5330 :         self.prepare(config);
     287         5330 :         self.mark_statement_roots();
     288         5330 :         self.prepare_precedence();
     289       456647 :         for i in 0..self.ast.len() {
     290       456647 :             self.identify_parentheses(self.ast.len() - 1 - i);
     291       456647 :         }
     292         5330 :         self.build_docs();
     293         5330 :         self.write_output()
     294         5330 :     }
     295              : 
     296              :     /// Format a single node (without the statement roots that only `format` marks)
     297          339 :     pub fn format_node_at(&mut self, node_id: usize, config: &FormattingConfigT) -> String {
     298          339 :         if node_id >= self.ast.len() {
     299            1 :             return String::new();
     300          338 :         }
     301          338 :         self.prepare(config);
     302          338 :         self.prepare_precedence();
     303         1736 :         for i in 0..self.ast.len() {
     304         1736 :             self.identify_parentheses(self.ast.len() - 1 - i);
     305         1736 :         }
     306          338 :         self.build_docs();
     307          338 :         self.render(self.node_states[node_id].reg)
     308          339 :     }
     309              : 
     310         5668 :     fn prepare(&mut self, config: &FormattingConfigT) {
     311         5668 :         self.config = config.clone();
     312         5668 :         self.fmt.reset();
     313         5668 :         self.fmt.set_config(config);
     314         5668 :         self.node_states.clear();
     315         5668 :         self.node_states.resize(self.ast.len(), FormattingNodeState::default());
     316         5668 :         self.unformattable_nodes.borrow_mut().clear();
     317         5668 :         self.copied_damaged_text.set(false);
     318         5668 :     }
     319              : 
     320         9476 :     fn mark_statement_roots(&mut self) {
     321         9759 :         for statement in &self.parsed.statements {
     322         9759 :             if (statement.root as usize) < self.node_states.len() {
     323         9759 :                 self.node_states[statement.root as usize].is_statement_root = true;
     324         9759 :                 self.mark_explain_inner_statement_root(statement.root as usize);
     325         9759 :             }
     326              :         }
     327         9476 :     }
     328              : 
     329         9759 :     fn mark_explain_inner_statement_root(&mut self, root_id: usize) {
     330         9759 :         let root_node = &self.ast[root_id];
     331         9759 :         if root_node.node_type() != NodeType::OBJECT_EXT_EXPLAIN {
     332         9535 :             return;
     333          224 :         }
     334          224 :         if let Some(child) = self.children(root_node).iter().find(|c| c.attribute_key() == K::EXT_EXPLAIN_STATEMENT) {
     335          224 :             let inner_id = self.node_id(child);
     336          224 :             if inner_id < self.node_states.len() {
     337          224 :                 self.node_states[inner_id].is_statement_root = true;
     338          224 :             }
     339            0 :         }
     340         9759 :     }
     341              : 
     342              :     // -----------------------------------------------------------------------------------------
     343              :     // AST access
     344              :     // -----------------------------------------------------------------------------------------
     345              : 
     346              :     /// The id of a node of the AST
     347       234768 :     fn node_id(&self, node: &Node) -> usize {
     348       234768 :         (node as *const Node as usize - self.ast.as_ptr() as usize) / std::mem::size_of::<Node>()
     349       234768 :     }
     350              : 
     351       207398 :     fn state(&self, node: &Node) -> &FormattingNodeState {
     352       207398 :         &self.node_states[self.node_id(node)]
     353       207398 :     }
     354              : 
     355              :     /// The document of a node
     356       207398 :     fn reg(&self, node: &Node) -> FmtReg {
     357       207398 :         self.state(node).reg
     358       207398 :     }
     359              : 
     360              :     /// The children of a node (`ast.subspan(children_begin_or_value, children_count)`)
     361       269402 :     fn children(&self, node: &Node) -> &'a [Node] {
     362       269402 :         let count = node.children_count() as usize;
     363       269402 :         if count == 0 {
     364          135 :             return &[];
     365       269267 :         }
     366       269267 :         let begin = node.children_begin_or_value() as usize;
     367       269267 :         &self.ast[begin..begin + count]
     368       269402 :     }
     369              : 
     370              :     /// The documents of the elements of an array
     371       157891 :     fn array_regs(&self, node: &Node) -> Vec<FmtReg> {
     372       157891 :         let count = node.children_count() as usize;
     373       157891 :         if count == 0 {
     374          150 :             return Vec::new();
     375       157741 :         }
     376       157741 :         let begin = node.children_begin_or_value() as usize;
     377       157741 :         self.node_states[begin..begin + count].iter().map(|s| s.reg).collect()
     378       157891 :     }
     379              : 
     380              :     /// Look up attributes of an object.
     381              :     ///
     382              :     /// A single key finds the first child with that key, several keys find the last child with each
     383              :     /// key (see docs/design/core_quirks.md).
     384         1241 :     fn attrs<const N: usize>(&self, node: &Node, keys: [AttributeKey; N]) -> [Option<&'a Node>; N] {
     385         1241 :         let mut out = [None; N];
     386         2482 :         for child in self.children(node) {
     387         4966 :             for (slot, key) in out.iter_mut().zip(keys.iter()) {
     388         4966 :                 if child.attribute_key() == *key {
     389         2482 :                     *slot = Some(child);
     390         2482 :                     if N == 1 {
     391            1 :                         return out;
     392         2481 :                     }
     393         2484 :                 }
     394              :             }
     395              :         }
     396         1240 :         out
     397         1241 :     }
     398              : 
     399              :     /// The text of a symbol span
     400       127484 :     fn text_at(&self, span: &SymbolSpan) -> &'a str {
     401       127484 :         let text: &'a str = &self.scanned.text;
     402       127484 :         let ts = resolve_text_span(text, &self.scanned.symbols, *span);
     403       127484 :         let begin = (ts.offset as usize).min(text.len());
     404       127484 :         let end = (begin + ts.length as usize).min(text.len());
     405       127484 :         &text[begin..end]
     406       127484 :     }
     407              : 
     408        12346 :     fn is_pretty(&self) -> bool {
     409        12346 :         self.config.mode == FormattingMode::PRETTY
     410        12346 :     }
     411              : 
     412              :     /// ForceBreak in pretty mode, `otherwise` in the other modes
     413        10123 :     fn pretty_policy(&self, otherwise: FormattingJoinPolicy) -> FormattingJoinPolicy {
     414        10123 :         if self.is_pretty() {
     415         3255 :             FormattingJoinPolicy::ForceBreak
     416              :         } else {
     417         6868 :             otherwise
     418              :         }
     419        10123 :     }
     420              : 
     421              :     // -----------------------------------------------------------------------------------------
     422              :     // Precedence
     423              :     // -----------------------------------------------------------------------------------------
     424              : 
     425         5668 :     fn prepare_precedence(&mut self) {
     426       458383 :         for i in 0..self.ast.len() {
     427       458383 :             let node = &self.ast[i];
     428       458383 :             if node.node_type() != NodeType::OBJECT_SQL_NARY_EXPRESSION {
     429       431253 :                 continue;
     430        27130 :             }
     431        27130 :             let [op_node, args_node] = attrs!(self.children(node), [K::SQL_EXPRESSION_OPERATOR, K::SQL_EXPRESSION_ARGS]);
     432        27130 :             let Some(op_node) = op_node else { continue };
     433              : 
     434        27130 :             let (precedence, associativity) = if op_node.node_type() == NodeType::ENUM_SQL_EXPRESSION_OPERATOR {
     435        26980 :                 get_operator_precedence(ExpressionOperator(value_u8(op_node)))
     436          150 :             } else if matches!(op_node.node_type(), NodeType::OPERATOR | NodeType::ARRAY) {
     437          150 :                 (11, Associativity::Left)
     438              :             } else {
     439            0 :                 continue;
     440              :             };
     441        27130 :             let state = &mut self.node_states[i];
     442        27130 :             state.precedence = precedence;
     443        27130 :             state.associativity = associativity;
     444        27130 :             if let Some(args_node) = args_node {
     445        27124 :                 let args_id = self.node_id(args_node);
     446        27124 :                 let args_state = &mut self.node_states[args_id];
     447        27124 :                 args_state.precedence = precedence;
     448        27124 :                 args_state.associativity = associativity;
     449        27124 :             }
     450              :         }
     451         5668 :     }
     452              : 
     453       458383 :     fn identify_parentheses(&mut self, node_id: usize) {
     454       458383 :         let node = &self.ast[node_id];
     455       458383 :         if node.node_type() != NodeType::OBJECT_SQL_NARY_EXPRESSION {
     456       431253 :             return;
     457        27130 :         }
     458        27130 :         let parent_id = node.parent() as usize;
     459        27130 :         if parent_id >= self.ast.len() {
     460            0 :             return;
     461        27130 :         }
     462        27130 :         let parent = &self.ast[parent_id];
     463        27130 :         if parent.node_type() != NodeType::ARRAY {
     464         8109 :             return;
     465        19021 :         }
     466        19021 :         let args_begin = parent.children_begin_or_value() as usize;
     467        19021 :         let args_count = parent.children_count() as usize;
     468        19021 :         if node_id < args_begin || node_id >= args_begin + args_count {
     469            0 :             return;
     470        19021 :         }
     471              : 
     472        19021 :         let arg_index = node_id - args_begin;
     473        19021 :         let parent_state = self.node_states[parent_id];
     474        19021 :         let state = &mut self.node_states[node_id];
     475        19021 :         let need_parens = if args_count == 1 {
     476           15 :             true
     477              :         } else {
     478        19006 :             let left_or_none = matches!(parent_state.associativity, Associativity::Left | Associativity::NonAssoc);
     479        19006 :             let right_or_none = matches!(parent_state.associativity, Associativity::Right | Associativity::NonAssoc);
     480        19006 :             state.precedence < parent_state.precedence
     481        18053 :                 || (state.precedence == parent_state.precedence
     482          567 :                     && ((arg_index == 0 && right_or_none)
     483          561 :                         || (arg_index == args_count - 1 && left_or_none)
     484          525 :                         || (arg_index > 0 && arg_index + 1 < args_count)))
     485              :         };
     486        19021 :         state.needs_parentheses = need_parens;
     487       458383 :     }
     488              : 
     489              :     // -----------------------------------------------------------------------------------------
     490              :     // Leaves and lists
     491              :     // -----------------------------------------------------------------------------------------
     492              : 
     493       126685 :     fn format_leaf(&self, node: &'a Node) -> FmtReg {
     494       126685 :         let text = self.text_at(node.symbol_span());
     495       126685 :         if self.replace_obfuscated_literals {
     496           12 :             let text_offset = resolve_text_span(&self.scanned.text, &self.scanned.symbols, *node.symbol_span()).offset;
     497           12 :             if let Some(literal) = self.find_obfuscated_literal(text_offset) {
     498            0 :                 return self.fmt.verbatim(&literal.replacement);
     499           12 :             }
     500       126673 :         }
     501       126685 :         if matches!(node.node_type(), NodeType::BOOL | NodeType::LITERAL_NULL | NodeType::OPERATOR) {
     502         4040 :             return self.fmt.text(text);
     503       122645 :         }
     504       122645 :         self.fmt.verbatim(text)
     505       126685 :     }
     506              : 
     507              :     /// The obfuscated literal whose marker starts at a text offset
     508           12 :     fn find_obfuscated_literal(&self, offset: u32) -> Option<&'a dashql_parser::scanner::ObfuscatedLiteral> {
     509           12 :         let literals: &'a [dashql_parser::scanner::ObfuscatedLiteral] = &self.scanned.obfuscated_literals;
     510           12 :         let i = literals.partition_point(|l| l.location.offset < offset);
     511           12 :         literals.get(i).filter(|l| l.location.offset == offset)
     512           12 :     }
     513              : 
     514           19 :     fn format_unimplemented(&self, node: &Node) -> FmtReg {
     515           19 :         self.unformattable_nodes.borrow_mut().push(self.node_id(node) as u32);
     516           19 :         let type_name = node.node_type().variant_name().unwrap_or("");
     517           19 :         let f = &self.fmt;
     518           19 :         f.concat(&[f.text("'<"), f.verbatim(type_name), f.text(">'")])
     519           19 :     }
     520              : 
     521              :     /// Format a node or record the child as unformattable (`reg_or_placeholder`)
     522         6115 :     fn reg_or_placeholder(&self, child: &Node) -> FmtReg {
     523         6115 :         let reg = self.reg(child);
     524         6115 :         if reg == 0 {
     525            0 :             return self.format_unimplemented(child);
     526         6115 :         }
     527         6115 :         reg
     528         6115 :     }
     529              : 
     530        65726 :     fn comma_separators(&self) -> (FmtReg, FmtReg) {
     531        65726 :         let f = &self.fmt;
     532        65726 :         let inline_separator = f.text(", ");
     533        65726 :         let break_separator = f.concat(&[f.text(","), f.break_()]);
     534        65726 :         (inline_separator, break_separator)
     535        65726 :     }
     536              : 
     537        58422 :     fn format_comma_list(&self, node: &Node, indent_after_breaks: bool) -> FmtReg {
     538        58422 :         let parts = self.array_regs(node);
     539        58422 :         let (inline_separator, break_separator) = self.comma_separators();
     540        58422 :         self.fmt.join(&parts, inline_separator, break_separator, None, indent_after_breaks)
     541        58422 :     }
     542              : 
     543              :     /// A comma-separated join that breaks on overflow
     544         6390 :     fn comma_join_on_overflow(&self, items: &[FmtReg], indent_after_breaks: bool) -> FmtReg {
     545         6390 :         let (inline_separator, break_separator) = self.comma_separators();
     546         6390 :         self.fmt.join(
     547         6390 :             items,
     548         6390 :             inline_separator,
     549         6390 :             break_separator,
     550         6390 :             Some(FormattingJoinPolicy::BreakOnOverflow),
     551         6390 :             indent_after_breaks,
     552              :         )
     553         6390 :     }
     554              : 
     555              :     /// A space-separated join
     556        18675 :     fn space_join(&self, items: &[FmtReg], policy: FormattingJoinPolicy, indent_after_breaks: bool) -> FmtReg {
     557        18675 :         let f = &self.fmt;
     558        18675 :         f.join(items, f.text(" "), f.break_(), Some(policy), indent_after_breaks)
     559        18675 :     }
     560              : 
     561        69237 :     fn format_qualified_name(&self, node: &Node) -> FmtReg {
     562        69237 :         let f = &self.fmt;
     563              :         // An index like `a[1]` follows its name without a dot
     564        69237 :         let mut parts: Vec<FmtReg> = Vec::new();
     565        78546 :         for (child, reg) in self.children(node).iter().zip(self.array_regs(node)) {
     566        78546 :             match parts.pop() {
     567         9309 :                 Some(previous) if child.node_type() == NodeType::OBJECT_SQL_INDIRECTION_INDEX => {
     568           81 :                     parts.push(f.concat(&[previous, reg]))
     569              :                 }
     570         9228 :                 Some(previous) => {
     571         9228 :                     parts.push(previous);
     572         9228 :                     parts.push(reg);
     573         9228 :                 }
     574        69237 :                 None => parts.push(reg),
     575              :             }
     576              :         }
     577        69237 :         if parts.is_empty() {
     578            0 :             return self.fmt.empty();
     579        69237 :         }
     580        69237 :         let inline_separator = f.text(".");
     581        69237 :         let break_separator = f.concat(&[f.break_(), f.text(".")]);
     582        69237 :         f.join(&parts, inline_separator, break_separator, None, true)
     583        69237 :     }
     584              : 
     585       128499 :     fn format_array(&self, node: &'a Node) -> FmtReg {
     586       128499 :         let f = &self.fmt;
     587       128499 :         if node.attribute_key() == K::NONE {
     588         1050 :             let parent_id = node.parent() as usize;
     589         1050 :             let parent = self.ast.get(parent_id);
     590         1050 :             let parent_key = parent.map(|p| p.attribute_key());
     591         1050 :             if parent_key == Some(K::SQL_SELECT_VALUES) {
     592          120 :                 return f.parenthesized(self.format_comma_list(node, true));
     593          930 :             }
     594          930 :             if parent_key == Some(K::SQL_EXPRESSION_ARGS) {
     595          798 :                 return self.format_comma_list(node, true);
     596          132 :             }
     597          132 :             if parent_key == Some(K::SQL_ROW_LOCKING_OF) {
     598           24 :                 return self.format_qualified_name(node);
     599          108 :             }
     600          108 :             if parent_key == Some(K::SQL_GRAPH_MATCH_PATTERNS) {
     601          108 :                 let parts = self.array_regs(node);
     602          108 :                 return f.join(&parts, f.empty(), f.break_(), Some(FormattingJoinPolicy::BreakOnOverflow), true);
     603            0 :             }
     604            0 :             if parent.is_some_and(|p| p.node_type() == NodeType::OBJECT_SQL_NARY_EXPRESSION) {
     605            0 :                 return self.format_comma_list(node, true);
     606            0 :             }
     607       127449 :         }
     608              : 
     609       127449 :         match node.attribute_key() {
     610              :             K::SQL_SELECT_TARGETS
     611              :             | K::SQL_SELECT_FROM
     612              :             | K::SQL_SELECT_GROUPS
     613              :             | K::SQL_SELECT_ORDER
     614              :             | K::SQL_WINDOW_FRAME_PARTITION
     615              :             | K::SQL_WINDOW_FRAME_ORDER
     616              :             | K::SQL_FUNCTION_WITHIN_GROUP
     617              :             | K::SQL_FUNCTION_ARGUMENTS
     618              :             | K::SQL_FUNCTION_ORDER
     619              :             | K::SQL_EXPRESSION_ARGS
     620              :             | K::SQL_DESCRIPTOR_COLUMNS
     621              :             | K::SQL_ROW_TYPE_FIELDS
     622              :             | K::SQL_CASE_CLAUSES
     623              :             | K::SQL_CREATE_TABLE_ELEMENTS
     624              :             | K::SQL_CREATE_AS_COLUMNS
     625              :             | K::SQL_VIEW_COLUMNS
     626              :             | K::SQL_CREATE_FUNCTION_PARAMS
     627              :             | K::SQL_SELECT_WINDOWS
     628              :             | K::SQL_SELECT_ROW_LOCKING
     629              :             | K::SQL_ROW_LOCKING_OF
     630              :             | K::SQL_GROUP_BY_ITEM_ARG
     631              :             | K::SQL_NUMERIC_TYPE_MODIFIERS
     632              :             | K::SQL_GENERIC_TYPE_MODIFIERS
     633              :             | K::SQL_TYPENAME_ARRAY
     634              :             | K::SQL_ATTACH_DATABASE_OPTIONS
     635              :             | K::SQL_INSERT_COLUMNS
     636              :             | K::SQL_INSERT_RETURNING
     637              :             | K::SQL_DELETE_USING
     638              :             | K::SQL_DELETE_RETURNING
     639              :             | K::SQL_CTE_COLUMNS
     640              :             | K::SQL_GRAPH_ELEMENT_TABLE_LABELS
     641              :             | K::SQL_GRAPH_MATCH_PATTERNS
     642              :             | K::SQL_RESULT_TARGET_EXCLUDE
     643              :             | K::SQL_TYPETEST_TYPES
     644              :             | K::SQL_FUNCTION_TABLE_ROWS_FROM
     645              :             | K::SQL_COLUMN_DEF_OPTIONS
     646              :             | K::SQL_CTE_OPTIONS
     647              :             | K::SQL_CONST_CAST_FUNC_ARGS_LIST
     648              :             | K::SQL_ROWSFROM_ITEM_COLUMNS
     649              :             | K::SQL_TABLE_CONSTRAINT_DEFINITION
     650        53868 :             | K::SQL_COLUMN_CONSTRAINT_DEFINITION => self.format_comma_list(node, true),
     651              :             K::SQL_PROPERTY_GRAPH_VERTEX_TABLES
     652              :             | K::SQL_PROPERTY_GRAPH_EDGE_TABLES
     653              :             | K::SQL_GRAPH_ELEMENT_TABLE_KEY
     654              :             | K::SQL_GRAPH_VERTEX_REFERENCE_KEY
     655              :             | K::SQL_GRAPH_VERTEX_REFERENCE_COLUMNS
     656              :             | K::SQL_GRAPH_PROPERTIES_COLUMNS
     657              :             | K::SQL_GRAPH_PROPERTIES_EXCLUDE
     658          465 :             | K::SQL_GRAPH_TABLE_COLUMNS => self.format_comma_list(node, false),
     659              :             K::SQL_SUBQUERY_OPERATOR | K::SQL_DEFINITION_ARG_VALUE | K::SQL_EXPRESSION_OPERATOR => {
     660           21 :                 self.format_operator_path(node)
     661              :             }
     662          861 :             K::SQL_TABLE_CONSTRAINT_ATTRIBUTES | K::SQL_COLUMN_DEF_CONSTRAINTS => self.format_space_list(node),
     663           84 :             K::EXT_EXPLAIN_OPTIONS => self.format_comma_list(node, false),
     664              :             K::EXT_EXPLAIN_EXPRESSIONS => {
     665            9 :                 let parts = self.array_regs(node);
     666            9 :                 let (inline_separator, break_separator) = self.comma_separators();
     667            9 :                 f.join(&parts, inline_separator, break_separator, Some(FormattingJoinPolicy::ForceBreak), false)
     668              :             }
     669              :             K::EXT_VARARG_FIELD_VALUE | K::SQL_GENERIC_OPTION_VALUE => {
     670           39 :                 f.parenthesized(self.format_comma_list(node, true))
     671              :             }
     672          117 :             K::SQL_INDIRECTION_PATH | K::SQL_SELECT_EXPRESSION_INDIRECTION => self.format_indirection_path(node),
     673              :             K::SQL_ROW_EXPRESSION_VALUES | K::SQL_ARRAY_EXPRESSION_VALUES => {
     674          363 :                 let values = self.array_regs(node);
     675          759 :                 if values.iter().any(|&v| v == 0) {
     676            0 :                     return self.format_unimplemented(node);
     677          363 :                 }
     678          363 :                 self.comma_join_on_overflow(&values, true)
     679              :             }
     680              :             K::SQL_WINDOW_FRAME_BOUNDS => {
     681          126 :                 let bounds = self.array_regs(node);
     682          126 :                 if bounds.len() == 1 && bounds[0] != 0 {
     683           30 :                     return bounds[0];
     684           96 :                 }
     685           96 :                 if bounds.len() == 2 && bounds[0] != 0 && bounds[1] != 0 {
     686           96 :                     return f.concat(&[f.text("between "), bounds[0], f.text(" and "), bounds[1]]);
     687            0 :                 }
     688            0 :                 self.format_unimplemented(node)
     689              :             }
     690              :             K::SQL_SELECT_VALUES => {
     691           75 :                 let rows = self.array_regs(node);
     692          120 :                 if rows.iter().any(|&r| r == 0) {
     693            0 :                     return self.format_unimplemented(node);
     694           75 :                 }
     695           75 :                 let policy = self.pretty_policy(FormattingJoinPolicy::BreakOnOverflow);
     696           75 :                 let indent_after_breaks = !self.is_pretty();
     697           75 :                 let (inline_separator, break_separator) = self.comma_separators();
     698           75 :                 f.join(&rows, inline_separator, break_separator, Some(policy), indent_after_breaks)
     699              :             }
     700              :             K::SQL_TEMP_NAME
     701              :             | K::SQL_CREATE_TABLE_NAME
     702              :             | K::SQL_FUNCTION_NAME
     703              :             | K::SQL_CONST_CAST_FUNC_NAME
     704              :             | K::SQL_COLUMN_CONSTRAINT_COLLATE
     705              :             | K::SQL_TABLEREF_NAME
     706              :             | K::SQL_PARAMETER_NAME
     707              :             | K::SQL_TABLE_CONSTRAINT_REFERENCES_NAME
     708              :             | K::SQL_COLUMN_REF_PATH
     709              :             | K::SQL_COLUMN_DEF_COLLATE
     710              :             | K::SQL_CREATE_AS_NAME
     711              :             | K::SQL_VIEW_NAME
     712              :             | K::SQL_CREATE_FUNCTION_NAME
     713              :             | K::SQL_DROP_NAME
     714              :             | K::EXT_VARARG_FIELD_KEY
     715        69213 :             | K::SQL_GRAPH_TABLE_GRAPH => self.format_qualified_name(node),
     716              :             K::SQL_SELECT_DISTINCT
     717              :             | K::SQL_SELECT_WITH_CTES
     718              :             | K::SQL_COMBINE_INPUT
     719              :             | K::SQL_JOIN_INPUT
     720              :             | K::SQL_TABLE_CONSTRAINT_COLUMNS
     721              :             | K::SQL_TABLE_CONSTRAINT_REFERENCES_COLUMNS
     722              :             | K::SQL_JOIN_USING
     723              :             | K::SQL_FUNCTION_TRIM_INPUT
     724              :             | K::SQL_ALIAS_COLUMN_NAMES
     725              :             | K::SQL_ALIAS_COLUMN_DEFS
     726         2193 :             | K::EXT_VARARG_ARRAY_VALUES => self.format_comma_list(node, true),
     727           15 :             _ => self.format_unimplemented(node),
     728              :         }
     729       128499 :     }
     730              : 
     731              :     // -----------------------------------------------------------------------------------------
     732              :     // Table references
     733              :     // -----------------------------------------------------------------------------------------
     734              : 
     735        13150 :     fn format_table_ref(&self, node: &'a Node) -> FmtReg {
     736        13150 :         let f = &self.fmt;
     737        13150 :         let [name, alias, table, lateral, sample, only] = attrs!(self.children(node), [
     738              :                 K::SQL_TABLEREF_NAME,
     739              :                 K::SQL_TABLEREF_ALIAS,
     740              :                 K::SQL_TABLEREF_TABLE,
     741              :                 K::SQL_TABLEREF_LATERAL,
     742              :                 K::SQL_TABLEREF_SAMPLE,
     743              :                 K::SQL_TABLEREF_ONLY,
     744              :             ],
     745              :         );
     746              : 
     747        13150 :         let mut base_reg = 0;
     748        13150 :         if let Some(table) = table {
     749         1944 :             base_reg = self.reg(table);
     750         1944 :             if table.node_type() == NodeType::OBJECT_SQL_SELECT {
     751          918 :                 base_reg = f.parenthesized(base_reg);
     752         1026 :             }
     753        11206 :         } else if let Some(name) = name {
     754        11206 :             base_reg = self.reg(name);
     755        11206 :         }
     756        13150 :         if base_reg == 0 {
     757            0 :             return self.format_unimplemented(node);
     758        13150 :         }
     759        13150 :         if is_true(only) {
     760            9 :             base_reg = f.concat(&[f.text("only "), base_reg]);
     761        13141 :         }
     762        13150 :         if is_true(lateral) {
     763           48 :             base_reg = f.concat(&[f.text("lateral "), base_reg]);
     764        13102 :         }
     765        13150 :         if let Some(alias) = alias {
     766         2490 :             let alias_reg = self.reg(alias);
     767         2490 :             if alias_reg == 0 {
     768            0 :                 return self.format_unimplemented(node);
     769         2490 :             }
     770         2490 :             base_reg = f.concat(&[base_reg, f.text(" "), alias_reg]);
     771        10660 :         }
     772        13150 :         if let Some(sample) = sample {
     773           57 :             let sample_reg = self.reg(sample);
     774           57 :             if sample_reg == 0 {
     775            0 :                 return self.format_unimplemented(node);
     776           57 :             }
     777           57 :             base_reg = f.concat(&[base_reg, f.text(" "), sample_reg]);
     778        13093 :         }
     779        13150 :         base_reg
     780        13150 :     }
     781              : 
     782           51 :     fn format_into(&self, node: &'a Node) -> FmtReg {
     783           51 :         let f = &self.fmt;
     784           51 :         let [temp, name] = attrs!(self.children(node), [K::SQL_TEMP_TYPE, K::SQL_TEMP_NAME]);
     785           51 :         let Some(name) = name else { return self.format_unimplemented(node) };
     786           51 :         let mut parts = vec![f.text("into ")];
     787           51 :         if let Some(temp) = temp {
     788           51 :             if TempType(value_u8(temp)) != TempType::NONE {
     789            3 :                 parts.push(self.reg(temp));
     790            3 :                 parts.push(f.text(" "));
     791           48 :             }
     792            0 :         }
     793           51 :         parts.push(self.reg(name));
     794           51 :         f.concat(&parts)
     795           51 :     }
     796              : 
     797           78 :     fn format_window_def(&self, node: &'a Node) -> FmtReg {
     798           78 :         let f = &self.fmt;
     799           78 :         let [name, frame] = attrs!(self.children(node), [K::SQL_WINDOW_DEF_NAME, K::SQL_WINDOW_DEF_FRAME]);
     800           78 :         let (Some(name), Some(frame)) = (name, frame) else { return self.format_unimplemented(node) };
     801              :         // An empty window specification is still a pair of parentheses
     802           78 :         let frame_reg = self.reg(frame);
     803           78 :         let frame_reg = if frame_reg == 0 { f.text("()") } else { f.parenthesized(frame_reg) };
     804           78 :         f.concat(&[self.reg(name), f.text(" as "), frame_reg])
     805           78 :     }
     806              : 
     807           81 :     fn format_row_locking_strength(&self, node: &'a Node) -> FmtReg {
     808           81 :         let text = match RowLockingStrength(value_u8(node)) {
     809           33 :             RowLockingStrength::UPDATE => "for update",
     810           12 :             RowLockingStrength::NO_KEY_UPDATE => "for no key update",
     811           12 :             RowLockingStrength::SHARE => "for share",
     812           12 :             RowLockingStrength::KEY_SHARE => "for key share",
     813           12 :             RowLockingStrength::READ_ONLY => "for read only",
     814            0 :             _ => return self.format_unimplemented(node),
     815              :         };
     816           81 :         self.fmt.text(text)
     817           81 :     }
     818              : 
     819           30 :     fn format_row_locking_block_behavior(&self, node: &'a Node) -> FmtReg {
     820           30 :         let text = match RowLockingBlockBehavior(value_u8(node)) {
     821           15 :             RowLockingBlockBehavior::NOWAIT => "nowait",
     822           15 :             RowLockingBlockBehavior::SKIP_LOCKED => "skip locked",
     823            0 :             _ => return self.format_unimplemented(node),
     824              :         };
     825           30 :         self.fmt.text(text)
     826           30 :     }
     827              : 
     828           81 :     fn format_row_locking(&self, node: &'a Node) -> FmtReg {
     829           81 :         let f = &self.fmt;
     830           81 :         let [strength, of, behavior] =
     831           81 :             attrs!(self.children(node), [K::SQL_ROW_LOCKING_STRENGTH, K::SQL_ROW_LOCKING_OF, K::SQL_ROW_LOCKING_BLOCK_BEHAVIOR]);
     832           81 :         let Some(strength) = strength else { return self.format_unimplemented(node) };
     833           81 :         let mut parts = vec![self.reg(strength)];
     834           81 :         if let Some(of) = of.filter(|of| of.children_count() > 0) {
     835           18 :             parts.push(f.text(" of "));
     836           18 :             parts.push(self.reg(of));
     837           63 :         }
     838           81 :         if let Some(behavior) = behavior {
     839           30 :             parts.push(f.text(" "));
     840           30 :             parts.push(self.reg(behavior));
     841           54 :         }
     842           81 :         f.concat(&parts)
     843           81 :     }
     844              : 
     845          105 :     fn format_sample_unit(&self, node: &'a Node) -> FmtReg {
     846          105 :         let text = match SampleCountUnit(value_u8(node)) {
     847           72 :             SampleCountUnit::PERCENT => "%",
     848           33 :             SampleCountUnit::ROWS => " rows",
     849            0 :             _ => return self.format_unimplemented(node),
     850              :         };
     851          105 :         self.fmt.text(text)
     852          105 :     }
     853              : 
     854          105 :     fn format_sample(&self, node: &'a Node, table_sample: bool) -> FmtReg {
     855          105 :         let f = &self.fmt;
     856          105 :         let [value, unit, function, repeat, seed] = attrs!(self.children(node), [
     857              :                 K::SQL_SAMPLE_COUNT_VALUE,
     858              :                 K::SQL_SAMPLE_COUNT_UNIT,
     859              :                 K::SQL_SAMPLE_FUNCTION,
     860              :                 K::SQL_SAMPLE_REPEAT,
     861              :                 K::SQL_SAMPLE_SEED,
     862              :             ],
     863              :         );
     864          105 :         let (Some(value), Some(unit)) = (value, unit) else { return self.format_unimplemented(node) };
     865              : 
     866              :         // Hyper only knows the word PERCENT for a table sample, DuckDB's `using sample` also takes `%`
     867          105 :         let is_percent = unit.node_type() == NodeType::ENUM_SQL_SAMPLE_UNIT_TYPE
     868          105 :             && SampleCountUnit(value_u8(unit)) == SampleCountUnit::PERCENT;
     869          105 :         let unit_reg = if table_sample && is_percent { f.text(" percent") } else { self.reg(unit) };
     870          105 :         let count = f.concat(&[self.reg(value), unit_reg]);
     871          105 :         let mut body = count;
     872          105 :         match (function, seed) {
     873            9 :             (Some(function), Some(seed)) => {
     874            9 :                 let args = f.concat(&[self.reg(function), f.text(", "), self.reg(seed)]);
     875            9 :                 body = f.concat(&[count, f.text(" "), f.parenthesized(args)]);
     876            9 :             }
     877           78 :             (Some(function), None) => body = f.concat(&[self.reg(function), f.parenthesized(count)]),
     878           18 :             _ => {}
     879              :         }
     880          105 :         if let Some(repeat) = repeat {
     881           24 :             body = f.concat(&[body, f.text(" repeatable "), f.parenthesized(self.reg(repeat))]);
     882           81 :         }
     883          105 :         f.concat(&[f.text(if table_sample { "tablesample " } else { "using sample " }), body])
     884          105 :     }
     885              : 
     886          687 :     fn format_joined_table(&self, node: &'a Node) -> FmtReg {
     887          687 :         let f = &self.fmt;
     888          687 :         let [inputs, join_type, join_on, join_using] =
     889          687 :             attrs!(self.children(node), [K::SQL_JOIN_INPUT, K::SQL_JOIN_TYPE, K::SQL_JOIN_ON, K::SQL_JOIN_USING]);
     890          687 :         let (Some(inputs), Some(join_type)) = (inputs, join_type) else { return self.format_unimplemented(node) };
     891          687 :         if inputs.node_type() != NodeType::ARRAY || inputs.children_count() != 2 {
     892            0 :             return self.format_unimplemented(node);
     893          687 :         }
     894              : 
     895          687 :         let left_reg = self.reg(&self.ast[inputs.children_begin_or_value() as usize]);
     896          687 :         let right_reg = self.reg(&self.ast[inputs.children_begin_or_value() as usize + 1]);
     897          687 :         if left_reg == 0 || right_reg == 0 {
     898            0 :             return self.format_unimplemented(node);
     899          687 :         }
     900              : 
     901          687 :         let join_text = match JoinType(value_u8(join_type)) {
     902           63 :             JoinType::NONE => "cross join",
     903          210 :             JoinType::INNER => "join",
     904          216 :             JoinType::LEFT | JoinType::OUTER_LEFT => "left join",
     905           12 :             JoinType::RIGHT | JoinType::OUTER_RIGHT => "right join",
     906           30 :             JoinType::FULL | JoinType::OUTER_FULL => "full join",
     907           39 :             JoinType::SEMI => "semi join",
     908           39 :             JoinType::ANTI => "anti join",
     909           30 :             JoinType::NATURAL_INNER => "natural join",
     910           24 :             JoinType::NATURAL_LEFT | JoinType::NATURAL_OUTER_LEFT => "natural left join",
     911           12 :             JoinType::NATURAL_RIGHT | JoinType::NATURAL_OUTER_RIGHT => "natural right join",
     912           12 :             JoinType::NATURAL_FULL | JoinType::NATURAL_OUTER_FULL => "natural full join",
     913            0 :             _ => return self.format_unimplemented(node),
     914              :         };
     915              : 
     916          687 :         let mut join_clause_parts = vec![f.concat(&[f.text(join_text), f.text(" "), right_reg])];
     917          687 :         if let Some(join_on) = join_on {
     918          528 :             let on_reg = self.reg(join_on);
     919          528 :             if on_reg == 0 {
     920            0 :                 return self.format_unimplemented(node);
     921          528 :             }
     922          528 :             join_clause_parts.push(f.concat(&[f.text("on "), on_reg]));
     923          159 :         } else if let Some(join_using) = join_using {
     924           18 :             let using_reg = self.reg(join_using);
     925           18 :             if using_reg == 0 {
     926            0 :                 return self.format_unimplemented(node);
     927           18 :             }
     928           18 :             join_clause_parts.push(f.concat(&[f.text("using "), f.parenthesized(using_reg)]));
     929          141 :         }
     930          687 :         let join_clause = self.space_join(&join_clause_parts, FormattingJoinPolicy::BreakOnOverflow, true);
     931              : 
     932          687 :         let clause_policy = self.pretty_policy(FormattingJoinPolicy::BreakAllOrNone);
     933          687 :         let mut is_left_nested_join = false;
     934          687 :         let table_ref_id = node.parent() as usize;
     935          687 :         if table_ref_id < self.ast.len() {
     936          687 :             let parent_id = self.ast[table_ref_id].parent() as usize;
     937          687 :             is_left_nested_join = parent_id < self.ast.len()
     938          687 :                 && self.ast[parent_id].node_type() == NodeType::ARRAY
     939          687 :                 && self.ast[parent_id].attribute_key() == K::SQL_JOIN_INPUT
     940          231 :                 && table_ref_id == self.ast[parent_id].children_begin_or_value() as usize;
     941            0 :         }
     942          687 :         self.space_join(&[left_reg, join_clause], clause_policy, !is_left_nested_join)
     943          687 :     }
     944              : 
     945         3879 :     fn format_group_by_item(&self, node: &'a Node) -> FmtReg {
     946         3879 :         let f = &self.fmt;
     947         3879 :         let [item_type, arg] = attrs!(self.children(node), [K::SQL_GROUP_BY_ITEM_TYPE, K::SQL_GROUP_BY_ITEM_ARG]);
     948         3879 :         let Some(item_type) = item_type.filter(|t| t.node_type() == NodeType::ENUM_SQL_GROUP_BY_ITEM_TYPE) else {
     949            0 :             return f.empty();
     950              :         };
     951         3879 :         let arg_reg = match arg {
     952         3873 :             Some(arg) if arg.node_type() != NodeType::NONE => self.reg(arg),
     953            6 :             _ => 0,
     954              :         };
     955         3879 :         let wrap = |keyword: &'static str| {
     956           90 :             if arg_reg == 0 {
     957            0 :                 return f.empty();
     958           90 :             }
     959           90 :             f.concat(&[f.text(keyword), f.parenthesized(arg_reg)])
     960           90 :         };
     961         3879 :         match GroupByItemType(value_u8(item_type)) {
     962         3786 :             GroupByItemType::EXPRESSION => arg_reg,
     963            3 :             GroupByItemType::EMPTY => f.text("()"),
     964            3 :             GroupByItemType::CUBE => wrap("cube"),
     965           84 :             GroupByItemType::ROLLUP => wrap("rollup"),
     966            3 :             GroupByItemType::GROUPING_SETS => wrap("grouping sets"),
     967            0 :             _ => f.empty(),
     968              :         }
     969         3879 :     }
     970              : 
     971              :     // -----------------------------------------------------------------------------------------
     972              :     // Types
     973              :     // -----------------------------------------------------------------------------------------
     974              : 
     975         2952 :     fn format_type_name(&self, node: &'a Node) -> FmtReg {
     976         2952 :         let f = &self.fmt;
     977         2952 :         let [type_node, array, setof] =
     978         2952 :             attrs!(self.children(node), [K::SQL_TYPENAME_TYPE, K::SQL_TYPENAME_ARRAY, K::SQL_TYPENAME_SETOF]);
     979         2952 :         let Some(type_node) = type_node else { return self.format_unimplemented(node) };
     980              : 
     981         2952 :         let mut type_reg = self.reg(type_node);
     982         2952 :         if let Some(array) = array.filter(|a| a.node_type() == NodeType::ARRAY) {
     983              :             // Hyper does not accept row(...)[], only array(row(...))
     984           57 :             let row_element = type_node.node_type() == NodeType::OBJECT_SQL_ROW_TYPE;
     985              :             // The keyword form `text array` has no children, a type without array has no text
     986           57 :             let keyword_form = array.children_count() == 0 && array.symbol_span().length() > 0;
     987           57 :             let bounds: Vec<Option<&Node>> =
     988           57 :                 if keyword_form { vec![None] } else { self.children(array).iter().map(Some).collect() };
     989           60 :             for bound in bounds {
     990           60 :                 let unbounded = bound.map_or(true, |b| b.node_type() == NodeType::BOOL);
     991           60 :                 if self.config.dialect == FormattingDialect::TRINO {
     992            6 :                     if !unbounded {
     993            0 :                         return self.format_unimplemented(node);
     994            6 :                     }
     995            6 :                     type_reg = f.concat(&[f.text("array("), type_reg, f.text(")")]);
     996           54 :                 } else if row_element && unbounded {
     997            6 :                     type_reg = f.concat(&[f.text("array("), type_reg, f.text(")")]);
     998            6 :                 } else {
     999           48 :                     let bound_reg = bound.filter(|b| b.node_type() != NodeType::BOOL).map_or(f.empty(), |b| self.reg(b));
    1000           48 :                     type_reg = f.concat(&[type_reg, f.text("["), bound_reg, f.text("]")]);
    1001              :                 }
    1002              :             }
    1003         2895 :         }
    1004              : 
    1005         2952 :         let mut parts = Vec::with_capacity(2);
    1006         2952 :         if is_true(setof) {
    1007            3 :             parts.push(f.text("setof "));
    1008         2949 :         }
    1009         2952 :         parts.push(type_reg);
    1010         2952 :         f.concat(&parts)
    1011         2952 :     }
    1012              : 
    1013          191 :     fn format_interval_type_enum(&self, node: &'a Node) -> FmtReg {
    1014          191 :         if node.node_type() != NodeType::ENUM_SQL_INTERVAL_TYPE {
    1015            0 :             return self.format_unimplemented(node);
    1016          191 :         }
    1017          191 :         match crate::analyzer::sql_types::interval_keyword(IntervalType(value_u8(node))) {
    1018          191 :             Some(text) => self.fmt.text(text),
    1019            0 :             None => self.format_unimplemented(node),
    1020              :         }
    1021          191 :     }
    1022              : 
    1023              :     /// The type of `interval '1' day` is the interval qualifier alone, a type name needs the keyword
    1024          215 :     fn format_interval_type(&self, node: &'a Node) -> FmtReg {
    1025          215 :         let f = &self.fmt;
    1026          215 :         let [interval_type, precision] = attrs!(self.children(node), [K::SQL_INTERVAL_TYPE, K::SQL_INTERVAL_PRECISION]);
    1027          215 :         let is_qualifier = node.attribute_key() == K::SQL_CONST_CAST_INTERVAL;
    1028          215 :         let mut parts = Vec::with_capacity(4);
    1029          215 :         if !is_qualifier {
    1030           57 :             parts.push(f.text("interval"));
    1031          158 :         }
    1032          215 :         if let Some(interval_type) = interval_type {
    1033          191 :             if !is_qualifier {
    1034           33 :                 parts.push(f.text(" "));
    1035          158 :             }
    1036          191 :             parts.push(self.reg(interval_type));
    1037           24 :         } else if is_qualifier {
    1038            0 :             return self.format_unimplemented(node);
    1039           24 :         }
    1040          215 :         if let Some(precision) = precision {
    1041           12 :             parts.push(f.parenthesized(self.reg(precision)));
    1042          203 :         }
    1043          215 :         f.concat(&parts)
    1044          215 :     }
    1045              : 
    1046           25 :     fn format_const_type_cast(&self, node: &'a Node) -> FmtReg {
    1047           25 :         let f = &self.fmt;
    1048           25 :         let [type_node, value] = attrs!(self.children(node), [K::SQL_CONST_CAST_TYPE, K::SQL_CONST_CAST_VALUE]);
    1049           25 :         let (Some(type_node), Some(value)) = (type_node, value) else { return self.format_unimplemented(node) };
    1050              :         // Trino reads the time zone of a timestamp or time literal from its text, its literals have no zone in the type
    1051           25 :         if self.config.dialect == FormattingDialect::TRINO {
    1052            1 :             if let Some(keyword) = self.zoned_time_type(type_node) {
    1053            1 :                 let value_reg = self.reg(value);
    1054            1 :                 if value_reg == 0 {
    1055            0 :                     return self.format_unimplemented(node);
    1056            1 :                 }
    1057            1 :                 return f.concat(&[f.text(keyword), f.text(" "), value_reg]);
    1058            0 :             }
    1059           24 :         }
    1060           24 :         let type_reg = self.reg(type_node);
    1061           24 :         let value_reg = self.reg(value);
    1062           24 :         if type_reg == 0 || value_reg == 0 {
    1063            0 :             return self.format_unimplemented(node);
    1064           24 :         }
    1065           24 :         f.concat(&[type_reg, f.text(" "), value_reg])
    1066           25 :     }
    1067              : 
    1068              :     /// The keyword of a timestamp or time type with a time zone, `timestamp with time zone` is `timestamp`
    1069            1 :     fn zoned_time_type(&self, type_node: &'a Node) -> Option<&'static str> {
    1070            1 :         let [element] = attrs!(self.children(type_node), [K::SQL_TYPENAME_TYPE]);
    1071            1 :         let element = element?;
    1072            1 :         let [tz] = attrs!(self.children(element), [K::SQL_TIME_TYPE_WITH_TIMEZONE]);
    1073            1 :         let zoned = tz.is_some_and(|t| t.node_type() == NodeType::BOOL && t.children_begin_or_value() != 0);
    1074            1 :         match element.node_type() {
    1075            1 :             NodeType::OBJECT_SQL_TIMESTAMP_TYPE if zoned => Some("timestamp"),
    1076            0 :             NodeType::OBJECT_SQL_TIME_TYPE if zoned => Some("time"),
    1077            0 :             _ => None,
    1078              :         }
    1079            1 :     }
    1080              : 
    1081          173 :     fn format_const_interval_cast(&self, node: &'a Node) -> FmtReg {
    1082          173 :         let f = &self.fmt;
    1083          173 :         let [value, interval] = attrs!(self.children(node), [K::SQL_CONST_CAST_VALUE, K::SQL_CONST_CAST_INTERVAL]);
    1084          173 :         let Some(value) = value else { return self.format_unimplemented(node) };
    1085          173 :         let mut parts = vec![f.text("interval "), self.reg(value)];
    1086          173 :         if let Some(interval) = interval {
    1087          158 :             parts.push(f.text(" "));
    1088          158 :             parts.push(self.reg(interval));
    1089          158 :         }
    1090          173 :         f.concat(&parts)
    1091          173 :     }
    1092              : 
    1093              :     /// The arguments of a function call, None if an argument cannot be formatted
    1094         6607 :     fn format_call_arguments(&self, args: Option<&'a Node>) -> Option<Vec<FmtReg>> {
    1095         6607 :         let mut arg_items = Vec::new();
    1096         6607 :         if let Some(args) = args {
    1097         5982 :             if args.node_type() != NodeType::ARRAY {
    1098            0 :                 return None;
    1099         5982 :             }
    1100         7122 :             for arg in self.children(args) {
    1101         7122 :                 let reg = self.reg(arg);
    1102         7122 :                 if reg == 0 {
    1103            0 :                     return None;
    1104         7122 :                 }
    1105         7122 :                 arg_items.push(reg);
    1106              :             }
    1107          625 :         }
    1108         6607 :         Some(arg_items)
    1109         6607 :     }
    1110              : 
    1111          343 :     fn format_const_function_cast(&self, node: &'a Node) -> FmtReg {
    1112          343 :         let f = &self.fmt;
    1113          343 :         let [name, args, order, value] = attrs!(self.children(node), [
    1114              :                 K::SQL_CONST_CAST_FUNC_NAME,
    1115              :                 K::SQL_CONST_CAST_FUNC_ARGS_LIST,
    1116              :                 K::SQL_CONST_CAST_FUNC_ARGS_ORDER,
    1117              :                 K::SQL_CONST_CAST_VALUE,
    1118              :             ],
    1119              :         );
    1120          343 :         let (Some(name), Some(value)) = (name, value) else { return self.format_unimplemented(node) };
    1121          343 :         let mut name_reg = self.reg(name);
    1122              :         // Trino reads the time zone of a timestamp or time literal from its text, `timestamptz '...'` is `timestamp '...'`
    1123          343 :         if self.config.dialect == FormattingDialect::TRINO && args.is_none() {
    1124           16 :             match self.text_at(name.symbol_span()).to_ascii_lowercase().as_str() {
    1125           16 :                 "timestamptz" => name_reg = f.text("timestamp"),
    1126           15 :                 "timetz" => name_reg = f.text("time"),
    1127           15 :                 _ => {}
    1128              :             }
    1129          327 :         }
    1130          343 :         let value_reg = self.reg(value);
    1131          343 :         if name_reg == 0 || value_reg == 0 {
    1132            0 :             return self.format_unimplemented(node);
    1133          343 :         }
    1134              : 
    1135          343 :         let Some(arg_items) = self.format_call_arguments(args) else { return self.format_unimplemented(node) };
    1136          343 :         let mut call_parts = Vec::with_capacity(3);
    1137          343 :         if !arg_items.is_empty() {
    1138            9 :             call_parts.push(self.comma_join_on_overflow(&arg_items, true));
    1139          334 :         }
    1140          343 :         if let Some(order) = order {
    1141            0 :             let order_reg = self.reg(order);
    1142            0 :             if order_reg == 0 {
    1143            0 :                 return self.format_unimplemented(node);
    1144            0 :             }
    1145            0 :             call_parts.push(f.text(if call_parts.is_empty() { "order by " } else { " order by " }));
    1146            0 :             call_parts.push(order_reg);
    1147          343 :         }
    1148              : 
    1149          343 :         let mut call_reg = name_reg;
    1150          343 :         if !call_parts.is_empty() {
    1151            9 :             let call_body = f.concat(&call_parts);
    1152            9 :             if call_body == 0 {
    1153            0 :                 return self.format_unimplemented(node);
    1154            9 :             }
    1155            9 :             call_reg = f.concat(&[name_reg, f.parenthesized(call_body)]);
    1156          334 :         }
    1157          343 :         f.concat(&[call_reg, f.text(" "), value_reg])
    1158          343 :     }
    1159              : 
    1160         1428 :     fn format_numeric_type_base(&self, node: &'a Node) -> FmtReg {
    1161         1428 :         if node.node_type() != NodeType::ENUM_SQL_NUMERIC_TYPE {
    1162            0 :             return self.format_unimplemented(node);
    1163         1428 :         }
    1164         1428 :         let text = match NumericType(value_u8(node)) {
    1165            0 :             NumericType::INT1 => "tinyint",
    1166            9 :             NumericType::INT2 => "smallint",
    1167          848 :             NumericType::INT4 => "integer",
    1168           24 :             NumericType::INT8 => "bigint",
    1169           21 :             NumericType::FLOAT4 => "real",
    1170           15 :             NumericType::FLOAT8 => "double precision",
    1171          496 :             NumericType::NUMERIC => "numeric",
    1172           15 :             NumericType::BOOL => "boolean",
    1173            0 :             _ => return self.format_unimplemented(node),
    1174              :         };
    1175         1428 :         self.fmt.text(text)
    1176         1428 :     }
    1177              : 
    1178              :     /// `(m1, m2, ...)` of a type with modifiers
    1179          487 :     fn format_type_modifiers(&self, modifiers: &'a Node) -> FmtReg {
    1180          968 :         let values: Vec<FmtReg> = self.children(modifiers).iter().map(|m| self.reg(m)).collect();
    1181          487 :         let (inline_separator, break_separator) = self.comma_separators();
    1182          487 :         let joined = self.fmt.join(&values, inline_separator, break_separator, None, true);
    1183          487 :         self.fmt.parenthesized(joined)
    1184          487 :     }
    1185              : 
    1186          496 :     fn format_numeric_type(&self, node: &'a Node) -> FmtReg {
    1187          496 :         let [base, modifiers] = attrs!(self.children(node), [K::SQL_NUMERIC_TYPE_BASE, K::SQL_NUMERIC_TYPE_MODIFIERS]);
    1188          496 :         let Some(base) = base else { return self.format_unimplemented(node) };
    1189          496 :         let mut parts = vec![self.reg(base)];
    1190          496 :         if let Some(modifiers) = modifiers.filter(|m| m.node_type() == NodeType::ARRAY && m.children_count() > 0) {
    1191          484 :             parts.push(self.format_type_modifiers(modifiers));
    1192          484 :         }
    1193          496 :         self.fmt.concat(&parts)
    1194          496 :     }
    1195              : 
    1196          447 :     fn format_character_type_base(&self, node: &'a Node) -> FmtReg {
    1197          447 :         if node.node_type() != NodeType::ENUM_SQL_CHARACTER_TYPE {
    1198            0 :             return self.format_unimplemented(node);
    1199          447 :         }
    1200          447 :         let text = match CharacterType(value_u8(node)) {
    1201          246 :             CharacterType::VARCHAR => "varchar",
    1202          201 :             CharacterType::BLANK_PADDED_CHAR => "char",
    1203            0 :             _ => return self.format_unimplemented(node),
    1204              :         };
    1205          447 :         self.fmt.text(text)
    1206          447 :     }
    1207              : 
    1208          447 :     fn format_character_type(&self, node: &'a Node) -> FmtReg {
    1209          447 :         let f = &self.fmt;
    1210          447 :         let [character_type, length] = attrs!(self.children(node), [K::SQL_CHARACTER_TYPE, K::SQL_CHARACTER_TYPE_LENGTH]);
    1211          447 :         let Some(character_type) = character_type else { return self.format_unimplemented(node) };
    1212          447 :         let mut parts = vec![self.reg(character_type)];
    1213          447 :         if let Some(length) = length {
    1214          372 :             parts.push(f.parenthesized(self.reg(length)));
    1215          375 :         }
    1216          447 :         f.concat(&parts)
    1217          447 :     }
    1218              : 
    1219          783 :     fn format_generic_type(&self, node: &'a Node) -> FmtReg {
    1220          783 :         let f = &self.fmt;
    1221          783 :         let [name, modifiers] = attrs!(self.children(node), [K::SQL_GENERIC_TYPE_NAME, K::SQL_GENERIC_TYPE_MODIFIERS]);
    1222          783 :         let Some(name) = name else { return self.format_unimplemented(node) };
    1223              : 
    1224          783 :         let name_text = self.text_at(name.symbol_span());
    1225          783 :         if name_text.eq_ignore_ascii_case("array") {
    1226           54 :             if let Some(modifiers) = modifiers.filter(|m| m.node_type() == NodeType::ARRAY && m.children_count() == 1) {
    1227           54 :                 let element_node = &self.ast[modifiers.children_begin_or_value() as usize];
    1228           54 :                 let element = self.reg(element_node);
    1229              :                 // Hyper does not accept row(...)[], only array(row(...))
    1230           54 :                 let [element_type] = attrs!(self.children(element_node), [K::SQL_TYPENAME_TYPE]);
    1231           54 :                 let row_element = element_type.is_some_and(|t| t.node_type() == NodeType::OBJECT_SQL_ROW_TYPE);
    1232           54 :                 if self.config.dialect == FormattingDialect::HYPER && !row_element {
    1233           12 :                     return f.concat(&[element, f.text("[]")]);
    1234           42 :                 }
    1235           42 :                 return f.concat(&[f.text("array("), element, f.text(")")]);
    1236            0 :             }
    1237          729 :         }
    1238              : 
    1239          729 :         let mut parts = vec![self.reg(name)];
    1240          729 :         if let Some(modifiers) = modifiers.filter(|m| m.node_type() == NodeType::ARRAY && m.children_count() > 0) {
    1241            3 :             parts.push(self.format_type_modifiers(modifiers));
    1242          726 :         }
    1243          729 :         f.concat(&parts)
    1244          783 :     }
    1245              : 
    1246           72 :     fn format_timestamp_type(&self, node: &'a Node) -> FmtReg {
    1247           72 :         let f = &self.fmt;
    1248           72 :         let [precision, with_tz] = attrs!(self.children(node), [K::SQL_TIME_TYPE_PRECISION, K::SQL_TIME_TYPE_WITH_TIMEZONE]);
    1249           72 :         let is_time = node.node_type() == NodeType::OBJECT_SQL_TIME_TYPE;
    1250           72 :         let mut parts = vec![f.text(if is_time { "time" } else { "timestamp" })];
    1251           72 :         if let Some(precision) = precision {
    1252           24 :             parts.push(f.parenthesized(self.reg(precision)));
    1253           48 :         }
    1254           72 :         if is_true(with_tz) {
    1255           33 :             parts.push(f.text(" with time zone"));
    1256           51 :         }
    1257           72 :         f.concat(&parts)
    1258           72 :     }
    1259              : 
    1260              :     // -----------------------------------------------------------------------------------------
    1261              :     // Ordering and enums
    1262              :     // -----------------------------------------------------------------------------------------
    1263              : 
    1264         3942 :     fn format_order(&self, node: &'a Node) -> FmtReg {
    1265         3942 :         let [value, direction, nullrule] =
    1266         3942 :             attrs!(self.children(node), [K::SQL_ORDER_VALUE, K::SQL_ORDER_DIRECTION, K::SQL_ORDER_NULLRULE]);
    1267         3942 :         let Some(value) = value else { return self.format_unimplemented(node) };
    1268         3942 :         let mut parts = vec![self.reg(value)];
    1269         3942 :         if let Some(direction) = direction {
    1270          498 :             parts.push(self.reg(direction));
    1271         3444 :         }
    1272         3942 :         if let Some(nullrule) = nullrule {
    1273         1473 :             parts.push(self.reg(nullrule));
    1274         2469 :         }
    1275         3942 :         self.space_join(&parts, FormattingJoinPolicy::BreakAllOrNone, true)
    1276         3942 :     }
    1277              : 
    1278          498 :     fn format_order_direction(&self, node: &'a Node) -> FmtReg {
    1279          498 :         if node.node_type() != NodeType::ENUM_SQL_ORDER_DIRECTION {
    1280            0 :             return self.format_unimplemented(node);
    1281          498 :         }
    1282          498 :         let text = match OrderDirection(value_u8(node)) {
    1283           87 :             OrderDirection::ASCENDING => "asc",
    1284          411 :             OrderDirection::DESCENDING => "desc",
    1285            0 :             _ => return self.format_unimplemented(node),
    1286              :         };
    1287          498 :         self.fmt.text(text)
    1288          498 :     }
    1289              : 
    1290         1473 :     fn format_order_null_rule(&self, node: &'a Node) -> FmtReg {
    1291         1473 :         if node.node_type() != NodeType::ENUM_SQL_ORDER_NULL_RULE {
    1292            0 :             return self.format_unimplemented(node);
    1293         1473 :         }
    1294         1473 :         let text = match OrderNullRule(value_u8(node)) {
    1295         1449 :             OrderNullRule::NULLS_FIRST => "nulls first",
    1296           24 :             OrderNullRule::NULLS_LAST => "nulls last",
    1297            0 :             _ => return self.format_unimplemented(node),
    1298              :         };
    1299         1473 :         self.fmt.text(text)
    1300         1473 :     }
    1301              : 
    1302           81 :     fn format_extract_target(&self, node: &'a Node) -> FmtReg {
    1303           81 :         if node.node_type() != NodeType::ENUM_SQL_EXTRACT_TARGET {
    1304            0 :             return self.format_unimplemented(node);
    1305           81 :         }
    1306           81 :         let text = match ExtractTarget(value_u8(node)) {
    1307           42 :             ExtractTarget::YEAR => "year",
    1308            6 :             ExtractTarget::MONTH => "month",
    1309           15 :             ExtractTarget::DAY => "day",
    1310            6 :             ExtractTarget::HOUR => "hour",
    1311            6 :             ExtractTarget::MINUTE => "minute",
    1312            6 :             ExtractTarget::SECOND => "second",
    1313            0 :             _ => return self.format_unimplemented(node),
    1314              :         };
    1315           81 :         self.fmt.text(text)
    1316           81 :     }
    1317              : 
    1318           66 :     fn format_trim_direction(&self, node: &'a Node) -> FmtReg {
    1319           66 :         if node.node_type() != NodeType::ENUM_SQL_TRIM_TARGET {
    1320            0 :             return self.format_unimplemented(node);
    1321           66 :         }
    1322           66 :         let text = match TrimDirection(value_u8(node)) {
    1323           39 :             TrimDirection::BOTH => "both",
    1324           15 :             TrimDirection::LEADING => "leading",
    1325           12 :             TrimDirection::TRAILING => "trailing",
    1326            0 :             _ => return self.format_unimplemented(node),
    1327              :         };
    1328           66 :         self.fmt.text(text)
    1329           66 :     }
    1330              : 
    1331              :     // -----------------------------------------------------------------------------------------
    1332              :     // References and rows
    1333              :     // -----------------------------------------------------------------------------------------
    1334              : 
    1335        50708 :     fn format_column_ref(&self, node: &'a Node) -> FmtReg {
    1336        50708 :         let [path] = attrs!(self.children(node), [K::SQL_COLUMN_REF_PATH]);
    1337        50708 :         match path {
    1338        50708 :             Some(path) => self.reg(path),
    1339            0 :             None => self.format_unimplemented(node),
    1340              :         }
    1341        50708 :     }
    1342              : 
    1343          279 :     fn format_parameter_ref(&self, node: &'a Node) -> FmtReg {
    1344          279 :         let [prefix, name] = attrs!(self.children(node), [K::SQL_PARAMETER_PREFIX, K::SQL_PARAMETER_NAME]);
    1345          279 :         let Some(prefix) = prefix else { return self.format_unimplemented(node) };
    1346          279 :         let prefix_reg = self.reg(prefix);
    1347          279 :         if prefix_reg == 0 {
    1348            0 :             return self.format_unimplemented(node);
    1349          279 :         }
    1350              :         // Positional parameters (?) have no name
    1351          279 :         let Some(name) = name else { return prefix_reg };
    1352          219 :         let name_reg = self.reg(name);
    1353          219 :         if name_reg == 0 {
    1354            0 :             return self.format_unimplemented(node);
    1355          219 :         }
    1356          219 :         self.fmt.concat(&[prefix_reg, name_reg])
    1357          279 :     }
    1358              : 
    1359              :     /// `<keyword>(<attribute>)`, unformattable without the attribute
    1360          417 :     fn format_keyword_call(&self, node: &'a Node, key: AttributeKey, keyword: &'static str) -> FmtReg {
    1361          417 :         let [child] = attrs!(self.children(node), [key]);
    1362          417 :         let Some(child) = child else { return self.format_unimplemented(node) };
    1363          417 :         let child_reg = self.reg(child);
    1364          417 :         if child_reg == 0 {
    1365            0 :             return self.format_unimplemented(node);
    1366          417 :         }
    1367          417 :         let f = &self.fmt;
    1368          417 :         f.concat(&[f.text(keyword), f.parenthesized(child_reg)])
    1369          417 :     }
    1370              : 
    1371           36 :     fn format_relation_expression(&self, node: &'a Node) -> FmtReg {
    1372           36 :         self.format_keyword_call(node, K::SQL_TABLEREF_NAME, "table")
    1373           36 :     }
    1374              : 
    1375           42 :     fn format_descriptor(&self, node: &'a Node) -> FmtReg {
    1376           42 :         self.format_keyword_call(node, K::SQL_DESCRIPTOR_COLUMNS, "descriptor")
    1377           42 :     }
    1378              : 
    1379          108 :     fn format_indirection(&self, node: &'a Node) -> FmtReg {
    1380          108 :         let [value, path] = attrs!(self.children(node), [K::SQL_INDIRECTION_VALUE, K::SQL_INDIRECTION_PATH]);
    1381          108 :         let (Some(value), Some(path)) = (value, path) else { return self.format_unimplemented(node) };
    1382          108 :         let value_reg = self.reg(value);
    1383          108 :         let path_reg = self.reg(path);
    1384          108 :         if value_reg == 0 || path_reg == 0 {
    1385            0 :             return self.format_unimplemented(node);
    1386          108 :         }
    1387          108 :         self.fmt.concat(&[self.fmt.parenthesized(value_reg), path_reg])
    1388          108 :     }
    1389              : 
    1390          135 :     fn format_row_type(&self, node: &'a Node) -> FmtReg {
    1391          135 :         self.format_keyword_call(node, K::SQL_ROW_TYPE_FIELDS, "row")
    1392          135 :     }
    1393              : 
    1394          258 :     fn format_row_expression(&self, node: &'a Node) -> FmtReg {
    1395          258 :         let f = &self.fmt;
    1396          258 :         let [is_explicit, values] = attrs!(self.children(node), [K::SQL_ROW_EXPRESSION_EXPLICIT, K::SQL_ROW_EXPRESSION_VALUES]);
    1397          258 :         let Some(values) = values.filter(|v| v.node_type() == NodeType::ARRAY) else {
    1398            0 :             return self.format_unimplemented(node);
    1399              :         };
    1400          258 :         if values.children_count() == 0 {
    1401           12 :             return f.text("row()");
    1402          246 :         }
    1403          246 :         let values_reg = self.reg(values);
    1404          246 :         if values_reg == 0 {
    1405            0 :             return self.format_unimplemented(node);
    1406          246 :         }
    1407              :         // (x) is just x, so a single value always needs the row keyword
    1408          246 :         if is_explicit.is_some() || values.children_count() == 1 {
    1409          102 :             return f.concat(&[f.text("row"), f.parenthesized(values_reg)]);
    1410          144 :         }
    1411          144 :         f.parenthesized(values_reg)
    1412          258 :     }
    1413              : 
    1414              :     /// `array[...]` or `array(select ...)`
    1415          126 :     fn format_array_expression(&self, node: &'a Node) -> FmtReg {
    1416          126 :         let f = &self.fmt;
    1417          126 :         let [values, statement] =
    1418          126 :             attrs!(self.children(node), [K::SQL_ARRAY_EXPRESSION_VALUES, K::SQL_ARRAY_EXPRESSION_STATEMENT]);
    1419          126 :         if statement.is_some() {
    1420           24 :             return self.format_keyword_call(node, K::SQL_ARRAY_EXPRESSION_STATEMENT, "array");
    1421          102 :         }
    1422          102 :         let Some(values) = values.filter(|v| v.node_type() == NodeType::ARRAY) else {
    1423            0 :             return self.format_unimplemented(node);
    1424              :         };
    1425          102 :         if values.children_count() == 0 {
    1426           12 :             return f.text("array[]");
    1427           90 :         }
    1428           90 :         let values_reg = self.reg(values);
    1429           90 :         if values_reg == 0 {
    1430            0 :             return self.format_unimplemented(node);
    1431           90 :         }
    1432           90 :         f.concat(&[f.text("array"), f.bracketed(values_reg)])
    1433          126 :     }
    1434              : 
    1435              :     // -----------------------------------------------------------------------------------------
    1436              :     // Column definitions and constraints
    1437              :     // -----------------------------------------------------------------------------------------
    1438              : 
    1439         1466 :     fn format_column_def(&self, node: &'a Node) -> FmtReg {
    1440         1466 :         let f = &self.fmt;
    1441              :         #[rustfmt::skip]
    1442         1466 :         let [name, type_node, options, constraints, collate] = attrs!(self.children(node), [
    1443              :             K::SQL_COLUMN_DEF_NAME,
    1444              :             K::SQL_COLUMN_DEF_TYPE,
    1445              :             K::SQL_COLUMN_DEF_OPTIONS,
    1446              :             K::SQL_COLUMN_DEF_CONSTRAINTS,
    1447              :             K::SQL_COLUMN_DEF_COLLATE,
    1448              :         ]);
    1449         1466 :         let (Some(name), Some(type_node)) = (name, type_node) else { return self.format_unimplemented(node) };
    1450              : 
    1451         1466 :         let mut parts = Vec::with_capacity(6);
    1452         1466 :         parts.push(self.reg_or_placeholder(name));
    1453         1466 :         parts.push(f.text(" "));
    1454         1466 :         parts.push(self.reg_or_placeholder(type_node));
    1455         1466 :         if let Some(collate) = collate {
    1456           21 :             parts.push(f.text(" collate "));
    1457           21 :             parts.push(self.reg_or_placeholder(collate));
    1458         1445 :         }
    1459              : 
    1460         1466 :         if let Some(options) = options {
    1461           12 :             if options.node_type() != NodeType::ARRAY {
    1462            0 :                 parts.push(f.text(" "));
    1463            0 :                 parts.push(self.format_unimplemented(options));
    1464           12 :             } else if options.children_count() > 0 {
    1465           12 :                 let option_parts: Vec<FmtReg> =
    1466           15 :                     self.children(options).iter().map(|o| self.reg_or_placeholder(o)).collect();
    1467           12 :                 let option_list = self.comma_join_on_overflow(&option_parts, true);
    1468           12 :                 parts.push(f.text(" options "));
    1469           12 :                 parts.push(f.parenthesized(option_list));
    1470            0 :             }
    1471         1454 :         }
    1472              : 
    1473         1466 :         if let Some(constraints) = constraints {
    1474          801 :             if constraints.node_type() != NodeType::ARRAY {
    1475            0 :                 parts.push(f.text(" "));
    1476            0 :                 parts.push(self.format_unimplemented(constraints));
    1477          801 :             } else if constraints.children_count() > 0 {
    1478          801 :                 let constraint_parts: Vec<FmtReg> =
    1479          816 :                     self.children(constraints).iter().map(|c| self.reg_or_placeholder(c)).collect();
    1480          801 :                 let constraint_list = self.space_join(&constraint_parts, FormattingJoinPolicy::BreakOnOverflow, true);
    1481          801 :                 parts.push(f.text(" "));
    1482          801 :                 parts.push(constraint_list);
    1483            0 :             }
    1484          665 :         }
    1485         1466 :         f.concat(&parts)
    1486         1466 :     }
    1487              : 
    1488          219 :     fn format_table_constraint_type(&self, node: &'a Node) -> FmtReg {
    1489          219 :         if node.node_type() != NodeType::ENUM_SQL_TABLE_CONSTRAINT {
    1490            0 :             return self.format_unimplemented(node);
    1491          219 :         }
    1492          219 :         let text = match TableConstraint(value_u8(node)) {
    1493           36 :             TableConstraint::CHECK => "check",
    1494           45 :             TableConstraint::UNIQUE => "unique",
    1495          123 :             TableConstraint::PRIMARY_KEY => "primary key",
    1496           15 :             TableConstraint::FOREIGN_KEY => "foreign key",
    1497            0 :             _ => return self.format_unimplemented(node),
    1498              :         };
    1499          219 :         self.fmt.text(text)
    1500          219 :     }
    1501              : 
    1502           12 :     fn format_key_match(&self, node: &'a Node) -> FmtReg {
    1503           12 :         if node.node_type() != NodeType::ENUM_SQL_KEY_MATCH {
    1504            0 :             return self.format_unimplemented(node);
    1505           12 :         }
    1506           12 :         let text = match KeyMatch(value_u8(node)) {
    1507            6 :             KeyMatch::FULL => "match full",
    1508            3 :             KeyMatch::PARTIAL => "match partial",
    1509            3 :             KeyMatch::SIMPLE => "match simple",
    1510            0 :             _ => return self.format_unimplemented(node),
    1511              :         };
    1512           12 :         self.fmt.text(text)
    1513           12 :     }
    1514              : 
    1515           21 :     fn format_key_action_command(&self, node: &'a Node) -> FmtReg {
    1516           21 :         if node.node_type() != NodeType::ENUM_SQL_KEY_ACTION_COMMAND {
    1517            0 :             return self.format_unimplemented(node);
    1518           21 :         }
    1519           21 :         let text = match KeyActionCommand(value_u8(node)) {
    1520            3 :             KeyActionCommand::NO_ACTION => "no action",
    1521            3 :             KeyActionCommand::RESTRICT => "restrict",
    1522            6 :             KeyActionCommand::CASCADE => "cascade",
    1523            6 :             KeyActionCommand::SET_NULL => "set null",
    1524            3 :             KeyActionCommand::SET_DEFAULT => "set default",
    1525            0 :             _ => return self.format_unimplemented(node),
    1526              :         };
    1527           21 :         self.fmt.text(text)
    1528           21 :     }
    1529              : 
    1530           21 :     fn format_key_action_trigger(&self, node: &'a Node) -> FmtReg {
    1531           21 :         if node.node_type() != NodeType::ENUM_SQL_KEY_ACTION_TRIGGER {
    1532            0 :             return self.format_unimplemented(node);
    1533           21 :         }
    1534           21 :         let text = match KeyActionTrigger(value_u8(node)) {
    1535            9 :             KeyActionTrigger::UPDATE => "on update",
    1536           12 :             KeyActionTrigger::DELETE => "on delete",
    1537            0 :             _ => return self.format_unimplemented(node),
    1538              :         };
    1539           21 :         self.fmt.text(text)
    1540           21 :     }
    1541              : 
    1542           21 :     fn format_key_action(&self, node: &'a Node) -> FmtReg {
    1543           21 :         let [trigger, command] = attrs!(self.children(node), [K::SQL_KEY_ACTION_TRIGGER, K::SQL_KEY_ACTION_COMMAND]);
    1544           21 :         let (Some(trigger), Some(command)) = (trigger, command) else { return self.format_unimplemented(node) };
    1545           21 :         self.space_join(&[self.reg(trigger), self.reg(command)], FormattingJoinPolicy::BreakAllOrNone, true)
    1546           21 :     }
    1547              : 
    1548              :     /// A space-separated list of constraint parts
    1549          936 :     fn format_space_list(&self, list: &'a Node) -> FmtReg {
    1550          936 :         if list.node_type() != NodeType::ARRAY {
    1551            0 :             return self.format_unimplemented(list);
    1552          936 :         }
    1553          936 :         if list.children_count() == 0 {
    1554            0 :             return self.fmt.empty();
    1555          936 :         }
    1556          975 :         let parts: Vec<FmtReg> = self.children(list).iter().map(|c| self.reg_or_placeholder(c)).collect();
    1557          936 :         self.space_join(&parts, FormattingJoinPolicy::BreakOnOverflow, true)
    1558          936 :     }
    1559              : 
    1560          219 :     fn format_table_constraint(&self, node: &'a Node) -> FmtReg {
    1561          219 :         let f = &self.fmt;
    1562              :         #[rustfmt::skip]
    1563              :         let [
    1564          219 :             constraint_type, constraint_name, constraint_argument, constraint_index, constraint_columns,
    1565          219 :             constraint_references_name, constraint_references_columns, constraint_attributes, constraint_definition,
    1566          219 :             constraint_key_actions, constraint_key_match,
    1567          219 :         ] = attrs!(self.children(node), [
    1568              :                 K::SQL_TABLE_CONSTRAINT_TYPE,
    1569              :                 K::SQL_TABLE_CONSTRAINT_NAME,
    1570              :                 K::SQL_TABLE_CONSTRAINT_ARGUMENT,
    1571              :                 K::SQL_TABLE_CONSTRAINT_INDEX,
    1572              :                 K::SQL_TABLE_CONSTRAINT_COLUMNS,
    1573              :                 K::SQL_TABLE_CONSTRAINT_REFERENCES_NAME,
    1574              :                 K::SQL_TABLE_CONSTRAINT_REFERENCES_COLUMNS,
    1575              :                 K::SQL_TABLE_CONSTRAINT_ATTRIBUTES,
    1576              :                 K::SQL_TABLE_CONSTRAINT_DEFINITION,
    1577              :                 K::SQL_TABLE_CONSTRAINT_KEY_ACTIONS,
    1578              :                 K::SQL_TABLE_CONSTRAINT_KEY_MATCH,
    1579              :             ],
    1580              :         );
    1581          219 :         let Some(constraint_type) = constraint_type.filter(|t| t.node_type() == NodeType::ENUM_SQL_TABLE_CONSTRAINT)
    1582              :         else {
    1583            0 :             return self.format_unimplemented(node);
    1584              :         };
    1585          228 :         let or_placeholder = |child: Option<&'a Node>| match child {
    1586          216 :             Some(child) => self.reg_or_placeholder(child),
    1587            0 :             None => self.format_unimplemented(node),
    1588          216 :         };
    1589              : 
    1590          219 :         let mut parts = Vec::with_capacity(16);
    1591          219 :         if let Some(constraint_name) = constraint_name {
    1592           15 :             parts.push(f.text("constraint "));
    1593           15 :             parts.push(self.reg_or_placeholder(constraint_name));
    1594           15 :             parts.push(f.text(" "));
    1595          204 :         }
    1596              : 
    1597          219 :         let ctype = TableConstraint(value_u8(constraint_type));
    1598          219 :         parts.push(self.reg_or_placeholder(constraint_type));
    1599          219 :         match ctype {
    1600           36 :             TableConstraint::CHECK => {
    1601           36 :                 parts.push(f.text(" "));
    1602           36 :                 parts.push(f.parenthesized(or_placeholder(constraint_argument)));
    1603           36 :             }
    1604              :             TableConstraint::UNIQUE | TableConstraint::PRIMARY_KEY => {
    1605          168 :                 if let Some(constraint_index) = constraint_index {
    1606           18 :                     parts.push(f.text(" using index "));
    1607           18 :                     parts.push(self.reg_or_placeholder(constraint_index));
    1608          150 :                 } else {
    1609          150 :                     parts.push(f.text(" "));
    1610          150 :                     parts.push(f.parenthesized(or_placeholder(constraint_columns)));
    1611          150 :                 }
    1612              :             }
    1613              :             TableConstraint::FOREIGN_KEY => {
    1614           15 :                 parts.push(f.text(" "));
    1615           15 :                 parts.push(f.parenthesized(or_placeholder(constraint_columns)));
    1616           15 :                 parts.push(f.text(" references "));
    1617           15 :                 parts.push(or_placeholder(constraint_references_name));
    1618            9 :                 if let Some(columns) =
    1619           15 :                     constraint_references_columns.filter(|c| c.node_type() == NodeType::ARRAY && c.children_count() > 0)
    1620            9 :                 {
    1621            9 :                     parts.push(f.text(" "));
    1622            9 :                     parts.push(f.parenthesized(self.reg_or_placeholder(columns)));
    1623            9 :                 }
    1624              :             }
    1625            0 :             _ => {}
    1626              :         }
    1627              : 
    1628          219 :         if let Some(constraint_key_match) = constraint_key_match {
    1629           12 :             parts.push(f.text(" "));
    1630           12 :             parts.push(self.reg_or_placeholder(constraint_key_match));
    1631          207 :         }
    1632          219 :         if let Some(constraint_key_actions) = constraint_key_actions {
    1633           15 :             let actions = self.format_space_list(constraint_key_actions);
    1634           15 :             if actions != 0 {
    1635           15 :                 parts.push(f.text(" "));
    1636           15 :                 parts.push(actions);
    1637           15 :             }
    1638          204 :         }
    1639          219 :         if let Some(constraint_attributes) = constraint_attributes {
    1640           60 :             let attributes = self.format_space_list(constraint_attributes);
    1641           60 :             if attributes != 0 {
    1642           60 :                 parts.push(f.text(" "));
    1643           60 :                 parts.push(attributes);
    1644           60 :             }
    1645          159 :         }
    1646          219 :         if let Some(constraint_definition) = constraint_definition {
    1647           12 :             let definition = self.reg_or_placeholder(constraint_definition);
    1648           12 :             if definition != 0 {
    1649           12 :                 parts.push(f.text(" with "));
    1650           12 :                 parts.push(f.parenthesized(definition));
    1651           12 :             }
    1652          207 :         }
    1653          219 :         f.concat(&parts)
    1654          219 :     }
    1655              : 
    1656          810 :     fn format_column_constraint_type(&self, node: &'a Node) -> FmtReg {
    1657          810 :         if node.node_type() != NodeType::ENUM_SQL_COLUMN_CONSTRAINT {
    1658            0 :             return self.format_unimplemented(node);
    1659          810 :         }
    1660          810 :         let text = match ColumnConstraint(value_u8(node)) {
    1661          759 :             ColumnConstraint::NOT_NULL => "not null",
    1662            3 :             ColumnConstraint::NULL_ => "null",
    1663            6 :             ColumnConstraint::UNIQUE => "unique",
    1664            9 :             ColumnConstraint::PRIMARY_KEY => "primary key",
    1665           12 :             ColumnConstraint::CHECK => "check",
    1666           12 :             ColumnConstraint::DEFAULT => "default",
    1667            9 :             ColumnConstraint::COLLATE => "collate",
    1668            0 :             _ => return self.format_unimplemented(node),
    1669              :         };
    1670          810 :         self.fmt.text(text)
    1671          810 :     }
    1672              : 
    1673          810 :     fn format_column_constraint(&self, node: &'a Node) -> FmtReg {
    1674          810 :         let f = &self.fmt;
    1675              :         #[rustfmt::skip]
    1676              :         let [
    1677          810 :             constraint_type, constraint_name, constraint_value, constraint_no_inherit, constraint_definition,
    1678          810 :             constraint_collate,
    1679          810 :         ] = attrs!(self.children(node), [
    1680              :                 K::SQL_COLUMN_CONSTRAINT_TYPE,
    1681              :                 K::SQL_COLUMN_CONSTRAINT_NAME,
    1682              :                 K::SQL_COLUMN_CONSTRAINT_VALUE,
    1683              :                 K::SQL_COLUMN_CONSTRAINT_NO_INHERIT,
    1684              :                 K::SQL_COLUMN_CONSTRAINT_DEFINITION,
    1685              :                 K::SQL_COLUMN_CONSTRAINT_COLLATE,
    1686              :             ],
    1687              :         );
    1688          810 :         let Some(constraint_type) = constraint_type.filter(|t| t.node_type() == NodeType::ENUM_SQL_COLUMN_CONSTRAINT)
    1689              :         else {
    1690            0 :             return self.format_unimplemented(node);
    1691              :         };
    1692          810 :         let or_placeholder = |child: Option<&'a Node>| match child {
    1693           33 :             Some(child) => self.reg_or_placeholder(child),
    1694            0 :             None => self.format_unimplemented(node),
    1695           33 :         };
    1696              : 
    1697          810 :         let mut parts = Vec::with_capacity(8);
    1698          810 :         if let Some(constraint_name) = constraint_name {
    1699           12 :             parts.push(f.text("constraint "));
    1700           12 :             parts.push(self.reg_or_placeholder(constraint_name));
    1701           12 :             parts.push(f.text(" "));
    1702          798 :         }
    1703              : 
    1704          810 :         let ctype = ColumnConstraint(value_u8(constraint_type));
    1705          810 :         parts.push(self.reg_or_placeholder(constraint_type));
    1706          810 :         match ctype {
    1707              :             ColumnConstraint::CHECK => {
    1708           12 :                 parts.push(f.text(" "));
    1709           12 :                 parts.push(f.parenthesized(or_placeholder(constraint_value)));
    1710           12 :                 if is_true(constraint_no_inherit) {
    1711            3 :                     parts.push(f.text(" no inherit"));
    1712            9 :                 }
    1713              :             }
    1714           12 :             ColumnConstraint::DEFAULT => {
    1715           12 :                 parts.push(f.text(" "));
    1716           12 :                 parts.push(or_placeholder(constraint_value));
    1717           12 :             }
    1718            9 :             ColumnConstraint::COLLATE => {
    1719            9 :                 parts.push(f.text(" "));
    1720            9 :                 parts.push(or_placeholder(constraint_collate));
    1721            9 :             }
    1722          777 :             _ => {}
    1723              :         }
    1724              : 
    1725          810 :         if let Some(constraint_definition) = constraint_definition {
    1726            0 :             let def_reg = self.reg_or_placeholder(constraint_definition);
    1727            0 :             if def_reg != 0 {
    1728            0 :                 parts.push(f.text(" with "));
    1729            0 :                 parts.push(f.parenthesized(def_reg));
    1730            0 :             }
    1731          810 :         }
    1732          810 :         f.concat(&parts)
    1733          810 :     }
    1734              : 
    1735           75 :     fn format_constraint_attribute(&self, node: &'a Node) -> FmtReg {
    1736           75 :         if node.node_type() != NodeType::ENUM_SQL_CONSTRAINT_ATTRIBUTE {
    1737            0 :             return self.format_unimplemented(node);
    1738           75 :         }
    1739           75 :         let text = match ConstraintAttribute(value_u8(node)) {
    1740           18 :             ConstraintAttribute::DEFERRABLE => "deferrable",
    1741            9 :             ConstraintAttribute::NOT_DEFERRABLE => "not deferrable",
    1742            9 :             ConstraintAttribute::INITIALLY_DEFERRED => "initially deferred",
    1743            9 :             ConstraintAttribute::INITIALLY_IMMEDIATE => "initially immediate",
    1744           15 :             ConstraintAttribute::NOT_VALID => "not valid",
    1745           15 :             ConstraintAttribute::NO_INHERIT => "no inherit",
    1746            0 :             _ => return self.format_unimplemented(node),
    1747              :         };
    1748           75 :         self.fmt.text(text)
    1749           75 :     }
    1750              : 
    1751          312 :     fn format_generic_option(&self, node: &'a Node) -> FmtReg {
    1752          312 :         let f = &self.fmt;
    1753          312 :         let [key, value] = attrs!(self.children(node), [K::SQL_GENERIC_OPTION_KEY, K::SQL_GENERIC_OPTION_VALUE]);
    1754          312 :         let Some(key) = key else { return self.format_unimplemented(node) };
    1755          312 :         let key_reg = self.reg(key);
    1756          282 :         match value {
    1757          282 :             Some(value) if value.node_type() != NodeType::NONE => f.concat(&[key_reg, f.text(" "), self.reg(value)]),
    1758           30 :             _ => key_reg,
    1759              :         }
    1760          312 :     }
    1761              : 
    1762              :     // -----------------------------------------------------------------------------------------
    1763              :     // Functions
    1764              :     // -----------------------------------------------------------------------------------------
    1765              : 
    1766         5787 :     fn format_function_arg(&self, node: &'a Node) -> FmtReg {
    1767         5787 :         let f = &self.fmt;
    1768         5787 :         let [arg_name, arg_value] = attrs!(self.children(node), [K::SQL_FUNCTION_ARG_NAME, K::SQL_FUNCTION_ARG_VALUE]);
    1769         5787 :         let Some(arg_value) = arg_value else { return self.format_unimplemented(node) };
    1770         5787 :         let value_reg = self.reg(arg_value);
    1771         5787 :         if value_reg == 0 {
    1772            0 :             return self.format_unimplemented(node);
    1773         5787 :         }
    1774         5787 :         let Some(arg_name) = arg_name else { return value_reg };
    1775           39 :         let name_reg = self.reg(arg_name);
    1776           39 :         if name_reg == 0 {
    1777            0 :             return self.format_unimplemented(node);
    1778           39 :         }
    1779           39 :         f.concat(&[name_reg, f.text(" => "), value_reg])
    1780         5787 :     }
    1781              : 
    1782              :     /// `name(<a> <keyword> <b>)` of the special function syntaxes, None if a part is missing
    1783         1239 :     fn format_special_call(
    1784         1239 :         &self,
    1785         1239 :         name_reg: FmtReg,
    1786         1239 :         args: &'a Node,
    1787         1239 :         keys: [AttributeKey; 2],
    1788         1239 :         keyword: &'static str,
    1789         1239 :     ) -> Option<FmtReg> {
    1790         1239 :         let f = &self.fmt;
    1791         1239 :         let [a, b] = self.attrs(args, keys);
    1792         1239 :         let a_reg = self.reg(a?);
    1793         1239 :         let b_reg = self.reg(b?);
    1794         1239 :         if a_reg == 0 || b_reg == 0 {
    1795            0 :             return None;
    1796         1239 :         }
    1797         1239 :         Some(f.concat(&[name_reg, f.parenthesized(f.concat(&[a_reg, f.text(keyword), b_reg]))]))
    1798         1239 :     }
    1799              : 
    1800         8187 :     fn format_function_expression(&self, node: &'a Node) -> FmtReg {
    1801         8187 :         let f = &self.fmt;
    1802              :         #[rustfmt::skip]
    1803              :         let [
    1804         8187 :             star, all, distinct, variadic, over, within_group, filter, name, args, order, cast_args, extract_args,
    1805         8187 :             overlay_args, position_args, substring_args, treat_args, trim_args,
    1806         8187 :         ] = attrs!(self.children(node), [
    1807              :                 K::SQL_FUNCTION_ARGUMENTS_STAR,
    1808              :                 K::SQL_FUNCTION_ALL,
    1809              :                 K::SQL_FUNCTION_DISTINCT,
    1810              :                 K::SQL_FUNCTION_VARIADIC,
    1811              :                 K::SQL_FUNCTION_OVER,
    1812              :                 K::SQL_FUNCTION_WITHIN_GROUP,
    1813              :                 K::SQL_FUNCTION_FILTER,
    1814              :                 K::SQL_FUNCTION_NAME,
    1815              :                 K::SQL_FUNCTION_ARGUMENTS,
    1816              :                 K::SQL_FUNCTION_ORDER,
    1817              :                 K::SQL_FUNCTION_CAST_ARGS,
    1818              :                 K::SQL_FUNCTION_EXTRACT_ARGS,
    1819              :                 K::SQL_FUNCTION_OVERLAY_ARGS,
    1820              :                 K::SQL_FUNCTION_POSITION_ARGS,
    1821              :                 K::SQL_FUNCTION_SUBSTRING_ARGS,
    1822              :                 K::SQL_FUNCTION_TREAT_ARGS,
    1823              :                 K::SQL_FUNCTION_TRIM_ARGS,
    1824              :             ],
    1825              :         );
    1826         8187 :         let Some(name) = name else { return self.format_unimplemented(node) };
    1827         8187 :         if all.is_some() && distinct.is_some() {
    1828            0 :             return self.format_unimplemented(node);
    1829         8187 :         }
    1830              : 
    1831         8187 :         let known_function_text = || {
    1832         2172 :             if name.node_type() != NodeType::ENUM_SQL_KNOWN_FUNCTION {
    1833            0 :                 return None;
    1834         2172 :             }
    1835         2172 :             Some(get_known_function_text(KnownFunction(value_u8(name)))).filter(|t| !t.is_empty())
    1836         2172 :         };
    1837              : 
    1838         8187 :         if cast_args.is_some()
    1839         7059 :             || extract_args.is_some()
    1840         6978 :             || overlay_args.is_some()
    1841         6960 :             || position_args.is_some()
    1842         6945 :             || substring_args.is_some()
    1843         6846 :             || treat_args.is_some()
    1844         6831 :             || trim_args.is_some()
    1845              :         {
    1846         1437 :             let Some(name_text) = known_function_text() else { return self.format_unimplemented(node) };
    1847         1437 :             let name_reg = f.text(name_text);
    1848              : 
    1849         1437 :             let special = if let Some(cast_args) = cast_args {
    1850         1128 :                 self.format_special_call(
    1851         1128 :                     name_reg,
    1852         1128 :                     cast_args,
    1853         1128 :                     [K::SQL_FUNCTION_CAST_VALUE, K::SQL_FUNCTION_CAST_TYPE],
    1854              :                     " as ",
    1855              :                 )
    1856          309 :             } else if let Some(extract_args) = extract_args {
    1857           81 :                 self.format_special_call(
    1858           81 :                     name_reg,
    1859           81 :                     extract_args,
    1860           81 :                     [K::SQL_FUNCTION_EXTRACT_TARGET, K::SQL_FUNCTION_EXTRACT_INPUT],
    1861              :                     " from ",
    1862              :                 )
    1863          228 :             } else if let Some(position_args) = position_args {
    1864           15 :                 self.format_special_call(
    1865           15 :                     name_reg,
    1866           15 :                     position_args,
    1867           15 :                     [K::SQL_FUNCTION_POSITION_SEARCH, K::SQL_FUNCTION_POSITION_INPUT],
    1868              :                     " in ",
    1869              :                 )
    1870          213 :             } else if let Some(treat_args) = treat_args {
    1871           15 :                 self.format_special_call(
    1872           15 :                     name_reg,
    1873           15 :                     treat_args,
    1874           15 :                     [K::SQL_FUNCTION_TREAT_VALUE, K::SQL_FUNCTION_TREAT_TYPE],
    1875              :                     " as ",
    1876              :                 )
    1877          198 :             } else if let Some(substring_args) = substring_args {
    1878           99 :                 self.format_substring_args(name_reg, substring_args)
    1879           99 :             } else if let Some(trim_args) = trim_args {
    1880           81 :                 self.format_trim_args(name_reg, trim_args)
    1881           18 :             } else if let Some(overlay_args) = overlay_args {
    1882           18 :                 self.format_overlay_args(name_reg, overlay_args)
    1883              :             } else {
    1884            0 :                 None
    1885              :             };
    1886         1437 :             return special.unwrap_or_else(|| self.format_unimplemented(node));
    1887         6750 :         }
    1888              : 
    1889         6750 :         let name_reg = if name.node_type() == NodeType::ARRAY {
    1890         6015 :             self.reg(name)
    1891          735 :         } else if let Some(name_text) = known_function_text() {
    1892          735 :             f.text(name_text)
    1893              :         } else {
    1894            0 :             return self.format_unimplemented(node);
    1895              :         };
    1896         6750 :         if name_reg == 0 {
    1897            0 :             return self.format_unimplemented(node);
    1898         6750 :         }
    1899              : 
    1900         6750 :         let mut call_parts = Vec::with_capacity(4);
    1901         6750 :         if star.is_some() {
    1902          486 :             if args.is_some() || variadic.is_some() || all.is_some() || distinct.is_some() || order.is_some() {
    1903            0 :                 return self.format_unimplemented(node);
    1904          486 :             }
    1905          486 :             call_parts.push(f.text("*"));
    1906              :         } else {
    1907         6264 :             let Some(mut arg_items) = self.format_call_arguments(args) else { return self.format_unimplemented(node) };
    1908         6264 :             if let Some(variadic) = variadic {
    1909            6 :                 let variadic_reg = self.reg(variadic);
    1910            6 :                 if variadic_reg == 0 {
    1911            0 :                     return self.format_unimplemented(node);
    1912            6 :                 }
    1913            6 :                 arg_items.push(f.concat(&[f.text("variadic "), variadic_reg]));
    1914         6258 :             }
    1915         6264 :             if all.is_some() || distinct.is_some() {
    1916          123 :                 if arg_items.is_empty() {
    1917            0 :                     return self.format_unimplemented(node);
    1918          123 :                 }
    1919          123 :                 call_parts.push(f.text(if all.is_some() { "all " } else { "distinct " }));
    1920         6141 :             }
    1921         6264 :             if !arg_items.is_empty() {
    1922         5976 :                 call_parts.push(self.comma_join_on_overflow(&arg_items, true));
    1923         5976 :             }
    1924              :         }
    1925              : 
    1926         6750 :         if let Some(order) = order {
    1927           18 :             let order_reg = self.reg(order);
    1928           18 :             if order_reg == 0 {
    1929            0 :                 return self.format_unimplemented(node);
    1930           18 :             }
    1931           18 :             call_parts.push(f.text(if call_parts.is_empty() { "order by " } else { " order by " }));
    1932           18 :             call_parts.push(order_reg);
    1933         6732 :         }
    1934              : 
    1935         6750 :         let call_body = f.concat(&call_parts);
    1936         6750 :         let mut result = if call_body == 0 {
    1937          288 :             if name.node_type() == NodeType::ENUM_SQL_KNOWN_FUNCTION {
    1938          117 :                 name_reg
    1939              :             } else {
    1940          171 :                 f.concat(&[name_reg, f.text("()")])
    1941              :             }
    1942              :         } else {
    1943         6462 :             f.concat(&[name_reg, f.parenthesized(call_body)])
    1944              :         };
    1945              : 
    1946         6750 :         if let Some(filter) = filter {
    1947           21 :             let filter_reg = self.reg(filter);
    1948           21 :             if filter_reg == 0 {
    1949            0 :                 return self.format_unimplemented(node);
    1950           21 :             }
    1951           21 :             let body = f.concat(&[f.text("where "), filter_reg]);
    1952           21 :             result = f.concat(&[result, f.text(" filter "), f.parenthesized(body)]);
    1953         6729 :         }
    1954         6750 :         if let Some(within_group) = within_group {
    1955           21 :             let wg_reg = self.reg(within_group);
    1956           21 :             if wg_reg == 0 {
    1957            0 :                 return self.format_unimplemented(node);
    1958           21 :             }
    1959           21 :             let body = f.concat(&[f.text("order by "), wg_reg]);
    1960           21 :             result = f.concat(&[result, f.text(" within group "), f.parenthesized(body)]);
    1961         6729 :         }
    1962         6750 :         if let Some(over) = over {
    1963          393 :             let over_reg = self.reg(over);
    1964          393 :             result = if over_reg == 0 {
    1965            9 :                 f.concat(&[result, f.text(" over ()")])
    1966          384 :             } else if over.node_type() == NodeType::NAME {
    1967              :                 // A reference to a named window, `over w`
    1968           33 :                 f.concat(&[result, f.text(" over "), over_reg])
    1969              :             } else {
    1970          351 :                 f.concat(&[result, f.text(" over "), f.parenthesized(over_reg)])
    1971              :             };
    1972         6357 :         }
    1973         6750 :         result
    1974         8187 :     }
    1975              : 
    1976           99 :     fn format_substring_args(&self, name_reg: FmtReg, args: &'a Node) -> Option<FmtReg> {
    1977           99 :         let f = &self.fmt;
    1978           99 :         let [sub_input, sub_from, sub_for] = attrs!(self.children(args), [K::SQL_FUNCTION_SUBSTRING_INPUT, K::SQL_FUNCTION_SUBSTRING_FROM, K::SQL_FUNCTION_SUBSTRING_FOR],
    1979              :         );
    1980           99 :         let input_reg = self.reg(sub_input?);
    1981           99 :         if input_reg == 0 {
    1982            0 :             return None;
    1983           99 :         }
    1984              :         // `substring(x from 2)`, `substring(x for 3)` or both
    1985           99 :         let mut parts = vec![input_reg];
    1986           99 :         if let Some(sub_from) = sub_from {
    1987           87 :             let from_reg = self.reg(sub_from);
    1988           87 :             if from_reg == 0 {
    1989            0 :                 return None;
    1990           87 :             }
    1991           87 :             parts.push(f.text(" from "));
    1992           87 :             parts.push(from_reg);
    1993           12 :         }
    1994           99 :         if let Some(sub_for) = sub_for {
    1995           78 :             let for_reg = self.reg(sub_for);
    1996           78 :             if for_reg == 0 {
    1997            0 :                 return None;
    1998           78 :             }
    1999           78 :             parts.push(f.text(" for "));
    2000           78 :             parts.push(for_reg);
    2001           21 :         } else if sub_from.is_none() {
    2002            0 :             return None;
    2003           21 :         }
    2004           99 :         Some(f.concat(&[name_reg, f.parenthesized(f.concat(&parts))]))
    2005           99 :     }
    2006              : 
    2007           81 :     fn format_trim_args(&self, name_reg: FmtReg, args: &'a Node) -> Option<FmtReg> {
    2008           81 :         let f = &self.fmt;
    2009           81 :         let [trim_input, trim_dir, trim_chars] = attrs!(self.children(args), [K::SQL_FUNCTION_TRIM_INPUT, K::SQL_FUNCTION_TRIM_DIRECTION, K::SQL_FUNCTION_TRIM_CHARACTERS]);
    2010           81 :         let input_reg = self.reg(trim_input?);
    2011           81 :         if input_reg == 0 {
    2012            0 :             return None;
    2013           81 :         }
    2014           81 :         let mut parts = Vec::with_capacity(6);
    2015           81 :         if let Some(trim_dir) = trim_dir {
    2016           66 :             let dir_reg = self.reg(trim_dir);
    2017           66 :             if dir_reg == 0 {
    2018            0 :                 return None;
    2019           66 :             }
    2020           66 :             parts.push(dir_reg);
    2021           66 :             parts.push(f.text(" "));
    2022           15 :         }
    2023           81 :         if let Some(trim_chars) = trim_chars {
    2024           33 :             let chars_reg = self.reg(trim_chars);
    2025           33 :             if chars_reg == 0 {
    2026            0 :                 return None;
    2027           33 :             }
    2028           33 :             parts.push(chars_reg);
    2029           33 :             parts.push(f.text(" "));
    2030           48 :         }
    2031           81 :         if trim_dir.is_some() || trim_chars.is_some() {
    2032           66 :             parts.push(f.text("from "));
    2033           66 :         }
    2034           81 :         parts.push(input_reg);
    2035           81 :         Some(f.concat(&[name_reg, f.parenthesized(f.concat(&parts))]))
    2036           81 :     }
    2037              : 
    2038           18 :     fn format_overlay_args(&self, name_reg: FmtReg, args: &'a Node) -> Option<FmtReg> {
    2039           18 :         let f = &self.fmt;
    2040           18 :         let [ov_input, ov_placing, ov_from, ov_for] = attrs!(self.children(args), [
    2041              :                 K::SQL_FUNCTION_OVERLAY_INPUT,
    2042              :                 K::SQL_FUNCTION_OVERLAY_PLACING,
    2043              :                 K::SQL_FUNCTION_OVERLAY_FROM,
    2044              :                 K::SQL_FUNCTION_OVERLAY_FOR,
    2045              :             ],
    2046              :         );
    2047           18 :         let (ov_input, ov_placing, ov_from) = (ov_input?, ov_placing?, ov_from?);
    2048           18 :         let input_reg = self.reg(ov_input);
    2049           18 :         let placing_reg = self.reg(ov_placing);
    2050           18 :         let from_reg = self.reg(ov_from);
    2051           18 :         if input_reg == 0 || placing_reg == 0 || from_reg == 0 {
    2052            0 :             return None;
    2053           18 :         }
    2054           18 :         let mut parts = vec![input_reg, f.text(" placing "), placing_reg, f.text(" from "), from_reg];
    2055           18 :         if let Some(ov_for) = ov_for {
    2056            6 :             let for_reg = self.reg(ov_for);
    2057            6 :             if for_reg == 0 {
    2058            0 :                 return None;
    2059            6 :             }
    2060            6 :             parts.push(f.text(" for "));
    2061            6 :             parts.push(for_reg);
    2062           12 :         }
    2063           18 :         Some(f.concat(&[name_reg, f.parenthesized(f.concat(&parts))]))
    2064           18 :     }
    2065              : 
    2066          150 :     fn format_function_table(&self, node: &'a Node) -> FmtReg {
    2067          150 :         let f = &self.fmt;
    2068          150 :         let [function, rows_from, with_ordinality] = attrs!(self.children(node), [K::SQL_FUNCTION_TABLE_FUNCTION, K::SQL_FUNCTION_TABLE_ROWS_FROM, K::SQL_FUNCTION_TABLE_WITH_ORDINALITY],
    2069              :         );
    2070          150 :         let mut base_reg = 0;
    2071          150 :         if let Some(function) = function {
    2072          120 :             base_reg = self.reg(function);
    2073          120 :         } else if let Some(rows_from) = rows_from {
    2074           30 :             let items = self.array_regs(rows_from);
    2075           60 :             if items.iter().any(|&i| i == 0) {
    2076            0 :                 return self.format_unimplemented(node);
    2077           30 :             }
    2078           30 :             let list = self.comma_join_on_overflow(&items, true);
    2079           30 :             base_reg = f.concat(&[f.text("rows from "), f.parenthesized(list)]);
    2080            0 :         }
    2081          150 :         if base_reg == 0 {
    2082            0 :             return self.format_unimplemented(node);
    2083          150 :         }
    2084          150 :         if is_true(with_ordinality) {
    2085           12 :             base_reg = f.concat(&[base_reg, f.text(" with ordinality")]);
    2086          138 :         }
    2087          150 :         base_reg
    2088          150 :     }
    2089              : 
    2090              :     // -----------------------------------------------------------------------------------------
    2091              :     // Windows
    2092              :     // -----------------------------------------------------------------------------------------
    2093              : 
    2094          438 :     fn format_window_frame(&self, node: &'a Node) -> FmtReg {
    2095          438 :         let f = &self.fmt;
    2096          438 :         let [partition, order, mode, bounds, exclude, name] = attrs!(self.children(node), [
    2097              :                 K::SQL_WINDOW_FRAME_PARTITION,
    2098              :                 K::SQL_WINDOW_FRAME_ORDER,
    2099              :                 K::SQL_WINDOW_FRAME_MODE,
    2100              :                 K::SQL_WINDOW_FRAME_BOUNDS,
    2101              :                 K::SQL_WINDOW_FRAME_EXCLUDE,
    2102              :                 K::SQL_WINDOW_FRAME_NAME,
    2103              :             ],
    2104              :         );
    2105          438 :         if exclude.is_some() || mode.is_none() != bounds.is_none() {
    2106            0 :             return self.format_unimplemented(node);
    2107          438 :         }
    2108              : 
    2109          438 :         let mut clauses = Vec::with_capacity(4);
    2110          438 :         if let Some(name) = name {
    2111            9 :             let name_reg = self.reg(name);
    2112            9 :             if name_reg == 0 {
    2113            0 :                 return self.format_unimplemented(node);
    2114            9 :             }
    2115            9 :             clauses.push(name_reg);
    2116          429 :         }
    2117          438 :         if let Some(partition) = partition {
    2118          258 :             let part_reg = self.reg(partition);
    2119          258 :             if part_reg == 0 {
    2120            0 :                 return self.format_unimplemented(node);
    2121          258 :             }
    2122          258 :             clauses.push(f.concat(&[f.text("partition by "), part_reg]));
    2123          180 :         }
    2124          438 :         if let Some(order) = order {
    2125          279 :             let order_reg = self.reg(order);
    2126          279 :             if order_reg == 0 {
    2127            0 :                 return self.format_unimplemented(node);
    2128          279 :             }
    2129          279 :             clauses.push(f.concat(&[f.text("order by "), order_reg]));
    2130          159 :         }
    2131          438 :         if let (Some(mode), Some(bounds)) = (mode, bounds) {
    2132          126 :             let mode_reg = self.reg(mode);
    2133          126 :             let bounds_reg = self.reg(bounds);
    2134          126 :             if mode_reg == 0 || bounds_reg == 0 {
    2135            0 :                 return self.format_unimplemented(node);
    2136          126 :             }
    2137          126 :             clauses.push(f.concat(&[mode_reg, f.text(" "), bounds_reg]));
    2138          312 :         }
    2139          438 :         if clauses.is_empty() {
    2140           21 :             return f.empty();
    2141          417 :         }
    2142          417 :         self.space_join(&clauses, FormattingJoinPolicy::BreakOnOverflow, true)
    2143          438 :     }
    2144              : 
    2145          222 :     fn format_window_bound(&self, node: &'a Node) -> FmtReg {
    2146          222 :         let f = &self.fmt;
    2147          222 :         let [mode, direction, value] =
    2148          222 :             attrs!(self.children(node), [K::SQL_WINDOW_BOUND_MODE, K::SQL_WINDOW_BOUND_DIRECTION, K::SQL_WINDOW_BOUND_VALUE]);
    2149          222 :         let Some(mode) = mode else { return self.format_unimplemented(node) };
    2150          222 :         match (WindowBoundMode(value_u8(mode)), direction, value) {
    2151           75 :             (WindowBoundMode::UNBOUNDED, Some(direction), None) => {
    2152           75 :                 f.concat(&[self.reg(mode), f.text(" "), self.reg(direction)])
    2153              :             }
    2154           84 :             (WindowBoundMode::CURRENT_ROW, None, None) => self.reg(mode),
    2155           63 :             (WindowBoundMode::VALUE, Some(direction), Some(value)) => {
    2156           63 :                 f.concat(&[self.reg(value), f.text(" "), self.reg(direction)])
    2157              :             }
    2158            0 :             _ => self.format_unimplemented(node),
    2159              :         }
    2160          222 :     }
    2161              : 
    2162          222 :     fn format_window_bound_mode(&self, node: &'a Node) -> FmtReg {
    2163          222 :         match WindowBoundMode(value_u8(node)) {
    2164           75 :             WindowBoundMode::UNBOUNDED => self.fmt.text("unbounded"),
    2165           84 :             WindowBoundMode::CURRENT_ROW => self.fmt.text("current row"),
    2166           63 :             WindowBoundMode::VALUE => self.fmt.empty(),
    2167            0 :             _ => self.format_unimplemented(node),
    2168              :         }
    2169          222 :     }
    2170              : 
    2171          138 :     fn format_window_bound_direction(&self, node: &'a Node) -> FmtReg {
    2172          138 :         match WindowBoundDirection(value_u8(node)) {
    2173          114 :             WindowBoundDirection::PRECEDING => self.fmt.text("preceding"),
    2174           24 :             WindowBoundDirection::FOLLOWING => self.fmt.text("following"),
    2175            0 :             _ => self.format_unimplemented(node),
    2176              :         }
    2177          138 :     }
    2178              : 
    2179          126 :     fn format_window_range_mode(&self, node: &'a Node) -> FmtReg {
    2180          126 :         match WindowRangeMode(value_u8(node)) {
    2181           18 :             WindowRangeMode::RANGE => self.fmt.text("range"),
    2182           90 :             WindowRangeMode::ROWS => self.fmt.text("rows"),
    2183           18 :             WindowRangeMode::GROUPS => self.fmt.text("groups"),
    2184            0 :             _ => self.format_unimplemented(node),
    2185              :         }
    2186          126 :     }
    2187              : 
    2188              :     // -----------------------------------------------------------------------------------------
    2189              :     // Expressions
    2190              :     // -----------------------------------------------------------------------------------------
    2191              : 
    2192          108 :     fn format_alias(&self, node: &'a Node) -> FmtReg {
    2193          108 :         let f = &self.fmt;
    2194          108 :         let [name, col_names, col_defs] =
    2195          108 :             attrs!(self.children(node), [K::SQL_ALIAS_NAME, K::SQL_ALIAS_COLUMN_NAMES, K::SQL_ALIAS_COLUMN_DEFS]);
    2196          108 :         let Some(name) = name else { return self.format_unimplemented(node) };
    2197          108 :         let name_reg = self.reg(name);
    2198          108 :         if name_reg == 0 {
    2199            0 :             return self.format_unimplemented(node);
    2200          108 :         }
    2201          108 :         for columns in [col_names, col_defs].into_iter().flatten() {
    2202           66 :             if columns.node_type() == NodeType::ARRAY && columns.children_count() > 0 {
    2203           66 :                 let cols = self.format_comma_list(columns, true);
    2204           66 :                 return f.concat(&[name_reg, f.parenthesized(cols)]);
    2205            0 :             }
    2206              :         }
    2207           42 :         name_reg
    2208          108 :     }
    2209              : 
    2210          141 :     fn format_typecast_expression(&self, node: &'a Node) -> FmtReg {
    2211          141 :         let f = &self.fmt;
    2212          141 :         let [value, type_node] = attrs!(self.children(node), [K::SQL_TYPECAST_VALUE, K::SQL_TYPECAST_TYPE]);
    2213          141 :         let (Some(value), Some(type_node)) = (value, type_node) else { return self.format_unimplemented(node) };
    2214          141 :         let mut value_reg = self.reg(value);
    2215          141 :         let type_reg = self.reg(type_node);
    2216          141 :         if value_reg == 0 || type_reg == 0 {
    2217            0 :             return self.format_unimplemented(node);
    2218          141 :         }
    2219          141 :         if value.node_type() == NodeType::OBJECT_SQL_NARY_EXPRESSION {
    2220           18 :             value_reg = f.parenthesized(value_reg);
    2221          123 :         }
    2222          141 :         f.concat(&[value_reg, f.text("::"), type_reg])
    2223          141 :     }
    2224              : 
    2225         1248 :     fn format_case(&self, node: &'a Node) -> FmtReg {
    2226         1248 :         let f = &self.fmt;
    2227         1248 :         let [argument, clauses, default_value] =
    2228         1248 :             attrs!(self.children(node), [K::SQL_CASE_ARGUMENT, K::SQL_CASE_CLAUSES, K::SQL_CASE_DEFAULT]);
    2229         1248 :         let Some(clauses) = clauses else { return self.format_unimplemented(node) };
    2230              : 
    2231         1248 :         let mut parts = Vec::new();
    2232         1248 :         if let Some(argument) = argument {
    2233           45 :             let arg_reg = self.reg(argument);
    2234           45 :             if arg_reg == 0 {
    2235            0 :                 return self.format_unimplemented(node);
    2236           45 :             }
    2237           45 :             parts.push(f.concat(&[f.text("case "), arg_reg]));
    2238         1203 :         } else {
    2239         1203 :             parts.push(f.text("case"));
    2240         1203 :         }
    2241         1278 :         for clause in self.array_regs(clauses) {
    2242         1278 :             if clause == 0 {
    2243            0 :                 return self.format_unimplemented(node);
    2244         1278 :             }
    2245         1278 :             parts.push(clause);
    2246              :         }
    2247         1248 :         if let Some(default_value) = default_value {
    2248         1179 :             let default_reg = self.reg(default_value);
    2249         1179 :             if default_reg == 0 {
    2250            0 :                 return self.format_unimplemented(node);
    2251         1179 :             }
    2252         1179 :             parts.push(f.concat(&[f.text("else "), default_reg]));
    2253           69 :         }
    2254         1248 :         parts.push(f.text("end"));
    2255              : 
    2256         1248 :         if self.is_pretty() {
    2257          416 :             let body = self.space_join(&parts[..parts.len() - 1], FormattingJoinPolicy::ForceBreak, true);
    2258          416 :             return self.space_join(&[body, parts[parts.len() - 1]], FormattingJoinPolicy::ForceBreak, false);
    2259          832 :         }
    2260          832 :         self.space_join(&parts, FormattingJoinPolicy::BreakOnOverflow, true)
    2261         1248 :     }
    2262              : 
    2263         1278 :     fn format_case_clause(&self, node: &'a Node) -> FmtReg {
    2264         1278 :         let f = &self.fmt;
    2265         1278 :         let [when_value, then_value] = attrs!(self.children(node), [K::SQL_CASE_CLAUSE_WHEN, K::SQL_CASE_CLAUSE_THEN]);
    2266         1278 :         let (Some(when_value), Some(then_value)) = (when_value, then_value) else {
    2267            0 :             return self.format_unimplemented(node);
    2268              :         };
    2269         1278 :         let when_reg = self.reg(when_value);
    2270         1278 :         let then_reg = self.reg(then_value);
    2271         1278 :         if when_reg == 0 || then_reg == 0 {
    2272            0 :             return self.format_unimplemented(node);
    2273         1278 :         }
    2274         1278 :         f.concat(&[f.text("when "), when_reg, f.text(" then "), then_reg])
    2275         1278 :     }
    2276              : 
    2277          180 :     fn format_exists_expression(&self, node: &'a Node) -> FmtReg {
    2278          180 :         self.format_keyword_call(node, K::SQL_EXISTS_EXPRESSION_STATEMENT, "exists ")
    2279          180 :     }
    2280              : 
    2281              :     /// `OPERATOR(schema.op)`, the elements are the qualifying names and the operator
    2282           21 :     fn format_operator_path(&self, node: &'a Node) -> FmtReg {
    2283           21 :         let f = &self.fmt;
    2284           21 :         let parts = self.array_regs(node);
    2285           42 :         if parts.is_empty() || parts.iter().any(|&p| p == 0) {
    2286            0 :             return self.format_unimplemented(node);
    2287           21 :         }
    2288           21 :         let joined = f.join(&parts, f.text("."), f.text("."), None, false);
    2289           21 :         f.concat(&[f.text("operator"), f.parenthesized(joined)])
    2290           21 :     }
    2291              : 
    2292              :     /// `a = any (select ...)`
    2293           99 :     fn format_subquery_expression(&self, node: &'a Node) -> FmtReg {
    2294           99 :         let f = &self.fmt;
    2295              :         #[rustfmt::skip]
    2296           99 :         let [arg0, arg1, operator, quantifier] = attrs!(self.children(node), [
    2297              :             K::SQL_SUBQUERY_ARG0, K::SQL_SUBQUERY_ARG1, K::SQL_SUBQUERY_OPERATOR, K::SQL_SUBQUERY_QUANTIFIER,
    2298              :         ]);
    2299           99 :         let (Some(arg0), Some(arg1), Some(operator), Some(quantifier)) = (arg0, arg1, operator, quantifier) else {
    2300            3 :             return self.format_unimplemented(node);
    2301              :         };
    2302           96 :         let (arg0_reg, arg1_reg, op_reg) = (self.reg(arg0), self.reg(arg1), self.reg(operator));
    2303           96 :         if arg0_reg == 0 || arg1_reg == 0 || op_reg == 0 {
    2304            0 :             return self.format_unimplemented(node);
    2305           96 :         }
    2306              :         // The right hand side is either a subquery, which parenthesizes itself, or an expression
    2307           96 :         let arg1_reg =
    2308           96 :             if arg1.node_type() == NodeType::OBJECT_SQL_SELECT_EXPRESSION { arg1_reg } else { f.parenthesized(arg1_reg) };
    2309           96 :         f.concat(&[arg0_reg, f.text(" "), op_reg, f.text(" "), self.reg(quantifier), f.text(" "), arg1_reg])
    2310           99 :     }
    2311              : 
    2312           99 :     fn format_subquery_quantifier(&self, node: &'a Node) -> FmtReg {
    2313           99 :         let text = match SubqueryQuantifier(value_u8(node)) {
    2314           63 :             SubqueryQuantifier::ANY => "any",
    2315           18 :             SubqueryQuantifier::SOME => "some",
    2316           18 :             SubqueryQuantifier::ALL => "all",
    2317            0 :             _ => return self.format_unimplemented(node),
    2318              :         };
    2319           99 :         self.fmt.text(text)
    2320           99 :     }
    2321              : 
    2322              :     /// `[value]` or `[lower:upper]`, a missing bound of a slice stays empty
    2323           93 :     fn format_indirection_index(&self, node: &'a Node) -> FmtReg {
    2324           93 :         let f = &self.fmt;
    2325           93 :         let [value, lower, upper] = attrs!(self.children(node), [
    2326              :             K::SQL_INDIRECTION_INDEX_VALUE,
    2327              :             K::SQL_INDIRECTION_INDEX_LOWER_BOUND,
    2328              :             K::SQL_INDIRECTION_INDEX_UPPER_BOUND,
    2329              :         ]);
    2330          159 :         let reg_of = |bound: Option<&'a Node>| bound.map_or(f.empty(), |b| self.reg(b));
    2331           93 :         if let Some(value) = value {
    2332           15 :             return f.concat(&[f.text("["), self.reg(value), f.text("]")]);
    2333           78 :         }
    2334           78 :         f.concat(&[f.text("["), reg_of(lower), f.text(":"), reg_of(upper), f.text("]")])
    2335           93 :     }
    2336              : 
    2337              :     /// The elements of a path after a value: `.field` and `[index]`
    2338          117 :     fn format_indirection_path(&self, node: &'a Node) -> FmtReg {
    2339          117 :         let f = &self.fmt;
    2340          117 :         let mut parts = Vec::with_capacity(node.children_count() as usize * 2);
    2341          117 :         for element in self.children(node) {
    2342          117 :             let reg = self.reg(element);
    2343          117 :             match element.node_type() {
    2344          105 :                 NodeType::NAME if reg != 0 => {
    2345          105 :                     parts.push(f.text("."));
    2346          105 :                     parts.push(reg);
    2347          105 :                 }
    2348           12 :                 NodeType::OBJECT_SQL_INDIRECTION_INDEX if reg != 0 => parts.push(reg),
    2349            0 :                 _ => return self.format_unimplemented(node),
    2350              :             }
    2351              :         }
    2352          117 :         f.concat(&parts)
    2353          117 :     }
    2354              : 
    2355              :     /// `a is [not] of (type, ...)`
    2356           18 :     fn format_typetest_expression(&self, node: &'a Node) -> FmtReg {
    2357           18 :         let f = &self.fmt;
    2358           18 :         let [negate, value, types] =
    2359           18 :             attrs!(self.children(node), [K::SQL_TYPETEST_NEGATE, K::SQL_TYPETEST_VALUE, K::SQL_TYPETEST_TYPES]);
    2360           18 :         let (Some(value), Some(types)) = (value, types) else { return self.format_unimplemented(node) };
    2361           18 :         let (value_reg, types_reg) = (self.reg(value), self.reg(types));
    2362           18 :         if value_reg == 0 || types_reg == 0 {
    2363            0 :             return self.format_unimplemented(node);
    2364           18 :         }
    2365           18 :         let keyword = if is_true(negate) { " is not of " } else { " is of " };
    2366           18 :         f.concat(&[value_reg, f.text(keyword), f.parenthesized(types_reg)])
    2367           18 :     }
    2368              : 
    2369              :     /// `f(...) [as (column definitions)]` of `rows from (...)`
    2370           60 :     fn format_rows_from_item(&self, node: &'a Node) -> FmtReg {
    2371           60 :         let f = &self.fmt;
    2372           60 :         let [function, columns] = attrs!(self.children(node), [K::SQL_ROWSFROM_ITEM_FUNCTION, K::SQL_ROWSFROM_ITEM_COLUMNS]);
    2373           60 :         let Some(function) = function else { return self.format_unimplemented(node) };
    2374           60 :         let function_reg = self.reg(function);
    2375           60 :         if function_reg == 0 {
    2376            0 :             return self.format_unimplemented(node);
    2377           60 :         }
    2378           60 :         match columns.filter(|c| c.node_type() == NodeType::ARRAY) {
    2379           27 :             Some(columns) => f.concat(&[function_reg, f.text(" as "), f.parenthesized(self.reg(columns))]),
    2380           33 :             None => function_reg,
    2381              :         }
    2382           60 :     }
    2383              : 
    2384              :     /// `bit [varying] [(length)]`
    2385           30 :     fn format_bit_type(&self, node: &'a Node) -> FmtReg {
    2386           30 :         let f = &self.fmt;
    2387           30 :         let [varying, length] = attrs!(self.children(node), [K::SQL_BIT_TYPE_VARYING, K::SQL_BIT_TYPE_LENGTH]);
    2388           30 :         let mut parts = vec![f.text(if is_true(varying) { "bit varying" } else { "bit" })];
    2389           30 :         if let Some(length) = length {
    2390           18 :             parts.push(f.parenthesized(self.reg(length)));
    2391           18 :         }
    2392           30 :         f.concat(&parts)
    2393           30 :     }
    2394              : 
    2395              :     /// `key = value` of a definition list
    2396           12 :     fn format_definition_arg(&self, node: &'a Node) -> FmtReg {
    2397           12 :         let f = &self.fmt;
    2398           12 :         let [key, value] = attrs!(self.children(node), [K::SQL_DEFINITION_ARG_KEY, K::SQL_DEFINITION_ARG_VALUE]);
    2399           12 :         let Some(key) = key else { return self.format_unimplemented(node) };
    2400           12 :         let value_reg = match value {
    2401           12 :             Some(value) => self.reg(value),
    2402            0 :             None => f.text("none"),
    2403              :         };
    2404           12 :         if value_reg == 0 {
    2405            0 :             return self.format_unimplemented(node);
    2406           12 :         }
    2407           12 :         f.concat(&[self.reg(key), f.text(" = "), value_reg])
    2408           12 :     }
    2409              : 
    2410          840 :     fn format_cte(&self, node: &'a Node) -> FmtReg {
    2411          840 :         let f = &self.fmt;
    2412          840 :         let [name, columns, statement, graph, secure, options] = attrs!(self.children(node), [
    2413              :                 K::SQL_CTE_NAME,
    2414              :                 K::SQL_CTE_COLUMNS,
    2415              :                 K::SQL_CTE_STATEMENT,
    2416              :                 K::SQL_CTE_PROPERTY_GRAPH,
    2417              :                 K::SQL_CTE_SECURE,
    2418              :                 K::SQL_CTE_OPTIONS,
    2419              :             ],
    2420              :         );
    2421          840 :         let Some(name) = name else { return self.format_unimplemented(node) };
    2422          840 :         let Some(body_node) = statement.or(graph) else { return self.format_unimplemented(node) };
    2423          840 :         let name_reg = self.reg(name);
    2424          840 :         let body_reg = self.reg(body_node);
    2425          840 :         if name_reg == 0 || body_reg == 0 {
    2426            0 :             return self.format_unimplemented(node);
    2427          840 :         }
    2428              : 
    2429          840 :         let body = if graph.is_some_and(|g| g.children_count() == 0) {
    2430           45 :             f.text("()")
    2431          795 :         } else if self.is_pretty() {
    2432          265 :             f.concat(&[f.text("("), f.indented(f.concat(&[f.break_(), body_reg])), f.break_(), f.text(")")])
    2433              :         } else {
    2434          530 :             f.parenthesized(body_reg)
    2435              :         };
    2436              : 
    2437          840 :         let as_reg = if graph.is_some() {
    2438           90 :             f.text(" as property graph ")
    2439          750 :         } else if secure.is_some() {
    2440           12 :             f.text(" as secure ")
    2441              :         } else {
    2442          738 :             f.text(" as ")
    2443              :         };
    2444          840 :         let mut result = match columns.filter(|c| c.node_type() == NodeType::ARRAY && c.children_count() > 0) {
    2445           21 :             Some(columns) => {
    2446           21 :                 let cols_reg = self.reg(columns);
    2447           21 :                 if cols_reg == 0 {
    2448            0 :                     return self.format_unimplemented(columns);
    2449           21 :                 }
    2450           21 :                 f.concat(&[name_reg, f.text(" "), f.parenthesized(cols_reg), as_reg, body])
    2451              :             }
    2452          819 :             None => f.concat(&[name_reg, as_reg, body]),
    2453              :         };
    2454          840 :         if let Some(options) = options {
    2455           36 :             let options_reg = self.reg(options);
    2456           36 :             if options_reg == 0 {
    2457            0 :                 return self.format_unimplemented(options);
    2458           36 :             }
    2459           36 :             result = f.concat(&[result, f.text(" options "), f.parenthesized(options_reg)]);
    2460          804 :         }
    2461          840 :         result
    2462          840 :     }
    2463              : 
    2464        27097 :     fn format_expression_operator_type(&self, node: &'a Node) -> FmtReg {
    2465        27097 :         if node.node_type() != NodeType::ENUM_SQL_EXPRESSION_OPERATOR {
    2466            0 :             return self.format_unimplemented(node);
    2467        27097 :         }
    2468        27097 :         let text = get_operator_text(ExpressionOperator(value_u8(node)));
    2469        27097 :         if text.is_empty() {
    2470            0 :             return self.format_unimplemented(node);
    2471        27097 :         }
    2472        27097 :         self.fmt.text(text)
    2473        27097 :     }
    2474              : 
    2475        20468 :     fn format_result_target(&self, node: &'a Node) -> FmtReg {
    2476        20468 :         let f = &self.fmt;
    2477        20468 :         let [value, name, star, exclude] = attrs!(self.children(node), [
    2478              :                 K::SQL_RESULT_TARGET_VALUE,
    2479              :                 K::SQL_RESULT_TARGET_NAME,
    2480              :                 K::SQL_RESULT_TARGET_STAR,
    2481              :                 K::SQL_RESULT_TARGET_EXCLUDE,
    2482              :             ],
    2483              :         );
    2484        20468 :         if let Some(star) = star {
    2485         1371 :             if name.is_some() {
    2486            0 :                 return self.format_unimplemented(node);
    2487         1371 :             }
    2488         1371 :             if star.node_type() != NodeType::BOOL || star.children_begin_or_value() == 0 {
    2489            0 :                 return self.format_unimplemented(star);
    2490         1371 :             }
    2491         1371 :             let mut result = match value {
    2492           21 :                 Some(value) => f.concat(&[self.reg(value), f.text(".*")]),
    2493         1350 :                 None => f.text("*"),
    2494              :             };
    2495         1371 :             if let Some(exclude) = exclude {
    2496           12 :                 let exclude_reg = self.reg(exclude);
    2497           12 :                 if exclude_reg == 0 {
    2498            0 :                     return self.format_unimplemented(exclude);
    2499           12 :                 }
    2500           12 :                 result = if exclude.children_count() == 1 {
    2501            3 :                     f.concat(&[result, f.text(" exclude "), exclude_reg])
    2502              :                 } else {
    2503            9 :                     f.concat(&[result, f.text(" exclude "), f.parenthesized(exclude_reg)])
    2504              :                 };
    2505         1359 :             }
    2506         1371 :             return result;
    2507        19097 :         }
    2508        19097 :         let Some(value) = value else { return self.format_unimplemented(node) };
    2509        19097 :         let value_reg = self.reg(value);
    2510        19097 :         if value_reg == 0 {
    2511            0 :             return self.format_unimplemented(value);
    2512        19097 :         }
    2513        19097 :         let Some(name) = name else { return value_reg };
    2514         8182 :         let name_reg = self.reg(name);
    2515         8182 :         if name_reg == 0 {
    2516            0 :             return self.format_unimplemented(name);
    2517         8182 :         }
    2518         8182 :         f.concat(&[value_reg, f.text(" as "), name_reg])
    2519        20468 :     }
    2520              : 
    2521          780 :     fn format_select_expression(&self, node: &'a Node) -> FmtReg {
    2522          780 :         let [statement, indirection] =
    2523          780 :             attrs!(self.children(node), [K::SQL_SELECT_EXPRESSION_STATEMENT, K::SQL_SELECT_EXPRESSION_INDIRECTION]);
    2524          780 :         let Some(statement) = statement else { return self.format_unimplemented(node) };
    2525          780 :         let subquery = self.fmt.parenthesized(self.reg(statement));
    2526          780 :         match indirection.filter(|i| i.node_type() == NodeType::ARRAY && i.children_count() > 0) {
    2527            9 :             Some(indirection) => self.fmt.concat(&[subquery, self.reg(indirection)]),
    2528          771 :             None => subquery,
    2529              :         }
    2530          780 :     }
    2531              : 
    2532              :     /// Is a DEFAULT expression a value of an INSERT ... VALUES?
    2533            6 :     fn is_in_insert_values(&self, node: &Node) -> bool {
    2534            6 :         let mut parent_id = node.parent() as usize;
    2535            6 :         let mut depth = 0;
    2536           18 :         while parent_id < self.ast.len() && depth < self.ast.len() {
    2537           18 :             let parent = &self.ast[parent_id];
    2538           18 :             if parent.attribute_key() == K::SQL_INSERT_SOURCE {
    2539            6 :                 let [values] = attrs!(self.children(parent), [K::SQL_SELECT_VALUES]);
    2540            6 :                 return parent.node_type() == NodeType::OBJECT_SQL_SELECT && values.is_some();
    2541           12 :             }
    2542           12 :             if parent.node_type() == NodeType::OBJECT_SQL_INSERT {
    2543            0 :                 break;
    2544           12 :             }
    2545           12 :             let next_parent = parent.parent() as usize;
    2546           12 :             if next_parent == parent_id {
    2547            0 :                 break;
    2548           12 :             }
    2549           12 :             parent_id = next_parent;
    2550           12 :             depth += 1;
    2551              :         }
    2552            0 :         false
    2553            6 :     }
    2554              : 
    2555        27130 :     fn format_expression(&self, node_id: usize) -> FmtReg {
    2556        27130 :         let f = &self.fmt;
    2557        27130 :         let node = &self.ast[node_id];
    2558        27130 :         let state = self.node_states[node_id];
    2559              : 
    2560        27130 :         let [op_node, args_node] = attrs!(self.children(node), [K::SQL_EXPRESSION_OPERATOR, K::SQL_EXPRESSION_ARGS]);
    2561        27130 :         if let (Some(op_node), None) = (op_node, args_node) {
    2562            6 :             if op_node.node_type() == NodeType::ENUM_SQL_EXPRESSION_OPERATOR
    2563            6 :                 && ExpressionOperator(value_u8(op_node)) == ExpressionOperator::DEFAULT
    2564              :             {
    2565            6 :                 if !self.is_in_insert_values(node) {
    2566            0 :                     return self.format_unimplemented(node);
    2567            6 :                 }
    2568            6 :                 return self.reg(op_node);
    2569            0 :             }
    2570        27124 :         }
    2571        27124 :         let (Some(op_node), Some(args_node)) = (op_node, args_node) else { return self.format_unimplemented(node) };
    2572            0 :         if !matches!(
    2573        27124 :             op_node.node_type(),
    2574              :             NodeType::ENUM_SQL_EXPRESSION_OPERATOR | NodeType::OPERATOR | NodeType::ARRAY
    2575        27124 :         ) || args_node.node_type() != NodeType::ARRAY
    2576        27124 :             || args_node.children_count() == 0
    2577              :         {
    2578            0 :             return self.format_unimplemented(node);
    2579        27124 :         }
    2580              : 
    2581        27124 :         let known_operator = op_node.node_type() == NodeType::ENUM_SQL_EXPRESSION_OPERATOR;
    2582        27124 :         let op = if known_operator { ExpressionOperator(value_u8(op_node)) } else { ExpressionOperator::DEFAULT };
    2583        27124 :         let op_reg = self.reg(op_node);
    2584        27124 :         if op_reg == 0 {
    2585            0 :             return self.format_unimplemented(node);
    2586        27124 :         }
    2587              : 
    2588        27124 :         let args = self.array_regs(args_node);
    2589        27124 :         if !known_operator && args.len() != 2 {
    2590            0 :             return self.format_unimplemented(node);
    2591        27124 :         }
    2592              : 
    2593              :         use ExpressionOperator as O;
    2594        27124 :         let mut reg = if args.len() == 1 && known_operator {
    2595          616 :             match op {
    2596          259 :                 O::NEGATE => f.concat(&[op_reg, args[0]]),
    2597           93 :                 O::NOT => f.concat(&[op_reg, f.text(" "), args[0]]),
    2598              :                 O::IS_NULL
    2599              :                 | O::NOT_NULL
    2600              :                 | O::IS_TRUE
    2601              :                 | O::IS_FALSE
    2602              :                 | O::IS_UNKNOWN
    2603              :                 | O::IS_NOT_TRUE
    2604              :                 | O::IS_NOT_FALSE
    2605          261 :                 | O::IS_NOT_UNKNOWN => f.concat(&[args[0], f.text(" "), op_reg]),
    2606            3 :                 _ => f.concat(&[op_reg, f.text(" "), args[0]]),
    2607              :             }
    2608        26508 :         } else if args.len() == 3
    2609         2436 :             && known_operator
    2610          879 :             && matches!(
    2611         2436 :                 op,
    2612              :                 O::BETWEEN_ASYMMETRIC | O::NOT_BETWEEN_ASYMMETRIC | O::BETWEEN_SYMMETRIC | O::NOT_BETWEEN_SYMMETRIC
    2613              :             )
    2614              :         {
    2615         1557 :             f.concat(&[args[0], f.text(" "), op_reg, f.text(" "), args[1], f.text(" and "), args[2]])
    2616        24951 :         } else if args.len() == 2 && known_operator && matches!(op, O::IN | O::NOT_IN) {
    2617         1104 :             let mut rhs = args[1];
    2618         1104 :             let rhs_node = &self.ast[args_node.children_begin_or_value() as usize + 1];
    2619         1104 :             if rhs_node.node_type() == NodeType::ARRAY {
    2620          789 :                 let list = self.format_comma_list(rhs_node, true);
    2621          789 :                 rhs = f.parenthesized(list);
    2622          789 :             }
    2623         1104 :             f.concat(&[args[0], f.text(" "), op_reg, f.text(" "), rhs])
    2624        23847 :         } else if args.len() == 2 && known_operator && matches!(op, O::IS_DISTINCT_FROM | O::IS_NOT_DISTINCT_FROM) {
    2625           30 :             f.concat(&[args[0], f.text(" "), op_reg, f.text(" "), args[1]])
    2626              :         } else {
    2627        23817 :             let is_boolean_chain = known_operator && matches!(op, O::AND | O::OR);
    2628        23817 :             let inline_separator = f.concat(&[f.text(" "), op_reg, f.text(" ")]);
    2629        23817 :             let break_separator = if breaks_before_operator(op) {
    2630         4137 :                 f.concat(&[f.break_(), op_reg, f.text(" ")])
    2631              :             } else {
    2632        19680 :                 f.concat(&[f.text(" "), op_reg, f.break_()])
    2633              :             };
    2634        23817 :             let policy = if is_boolean_chain { None } else { Some(FormattingJoinPolicy::BreakOnOverflow) };
    2635        23817 :             f.join(&args, inline_separator, break_separator, policy, true)
    2636              :         };
    2637              : 
    2638        27124 :         if state.needs_parentheses {
    2639         1004 :             reg = f.parenthesized(reg);
    2640        26120 :         }
    2641        27124 :         reg
    2642        27130 :     }
    2643              : 
    2644              :     // -----------------------------------------------------------------------------------------
    2645              :     // Dispatch
    2646              :     // -----------------------------------------------------------------------------------------
    2647              : 
    2648       458383 :     fn format_node(&self, node_id: usize) -> FmtReg {
    2649       458383 :         let node: &'a Node = &self.ast[node_id];
    2650       458383 :         let f = &self.fmt;
    2651       458383 :         match node.node_type() {
    2652       128499 :             NodeType::ARRAY => self.format_array(node),
    2653         8962 :             NodeType::OBJECT_SQL_SELECT => self.format_select(node_id),
    2654           90 :             NodeType::OBJECT_SQL_INSERT => self.format_insert(node),
    2655           84 :             NodeType::OBJECT_SQL_DELETE => self.format_delete(node),
    2656          335 :             NodeType::OBJECT_SQL_CREATE => self.format_create(node_id),
    2657           39 :             NodeType::OBJECT_SQL_CREATE_AS => self.format_create_as(node),
    2658           24 :             NodeType::OBJECT_SQL_VIEW => self.format_view(node),
    2659           45 :             NodeType::OBJECT_SQL_CREATE_FUNCTION => self.format_create_function(node),
    2660           21 :             NodeType::OBJECT_SQL_DROP_TABLE => self.format_drop(node, true),
    2661           21 :             NodeType::OBJECT_SQL_DROP_VIEW => self.format_drop(node, false),
    2662           18 :             NodeType::OBJECT_SQL_ATTACH_DATABASE => self.format_attach_database(node),
    2663           18 :             NodeType::OBJECT_SQL_ATTACH_DATABASE_OPTION => self.format_attach_database_option(node),
    2664           57 :             NodeType::OBJECT_SQL_FUNCTION_PARAM => self.format_function_param(node),
    2665           24 :             NodeType::OBJECT_EXT_SET => self.format_set(node),
    2666           78 :             NodeType::OBJECT_EXT_VARARG_FIELD => self.format_vararg_field(node),
    2667          126 :             NodeType::OBJECT_EXT_EXPLAIN => self.format_explain(node_id),
    2668            9 :             NodeType::OBJECT_EXT_EXPLAIN_EXPRESSIONS => self.format_explain_expressions(node),
    2669        13150 :             NodeType::OBJECT_SQL_TABLEREF => self.format_table_ref(node),
    2670          687 :             NodeType::OBJECT_SQL_JOINED_TABLE => self.format_joined_table(node),
    2671          687 :             NodeType::ENUM_SQL_JOIN_TYPE => f.empty(),
    2672           51 :             NodeType::OBJECT_SQL_INTO => self.format_into(node),
    2673           78 :             NodeType::OBJECT_SQL_WINDOW_DEF => self.format_window_def(node),
    2674           81 :             NodeType::OBJECT_SQL_ROW_LOCKING => self.format_row_locking(node),
    2675           81 :             NodeType::ENUM_SQL_ROW_LOCKING_STRENGTH => self.format_row_locking_strength(node),
    2676           30 :             NodeType::ENUM_SQL_ROW_LOCKING_BLOCK_BEHAVIOR => self.format_row_locking_block_behavior(node),
    2677           48 :             NodeType::OBJECT_SQL_SELECT_SAMPLE => self.format_sample(node, false),
    2678           57 :             NodeType::OBJECT_SQL_TABLEREF_SAMPLE => self.format_sample(node, true),
    2679          105 :             NodeType::ENUM_SQL_SAMPLE_UNIT_TYPE => self.format_sample_unit(node),
    2680         3879 :             NodeType::OBJECT_SQL_GROUP_BY_ITEM => self.format_group_by_item(node),
    2681              :             NodeType::ENUM_SQL_GROUP_BY_ITEM_TYPE
    2682              :             | NodeType::ENUM_SQL_COMBINE_MODIFIER
    2683         4767 :             | NodeType::ENUM_SQL_COMBINE_OPERATION => f.empty(),
    2684         3942 :             NodeType::OBJECT_SQL_ORDER => self.format_order(node),
    2685          498 :             NodeType::ENUM_SQL_ORDER_DIRECTION => self.format_order_direction(node),
    2686         1473 :             NodeType::ENUM_SQL_ORDER_NULL_RULE => self.format_order_null_rule(node),
    2687          105 :             NodeType::ENUM_SQL_TEMP_TYPE => self.format_temp_type(node),
    2688           33 :             NodeType::ENUM_SQL_ON_COMMIT_OPTION => self.format_on_commit_option(node),
    2689         2952 :             NodeType::OBJECT_SQL_TYPENAME => self.format_type_name(node),
    2690          215 :             NodeType::OBJECT_SQL_INTERVAL_TYPE => self.format_interval_type(node),
    2691          191 :             NodeType::ENUM_SQL_INTERVAL_TYPE => self.format_interval_type_enum(node),
    2692          496 :             NodeType::OBJECT_SQL_NUMERIC_TYPE => self.format_numeric_type(node),
    2693         1428 :             NodeType::ENUM_SQL_NUMERIC_TYPE => self.format_numeric_type_base(node),
    2694          447 :             NodeType::OBJECT_SQL_CHARACTER_TYPE => self.format_character_type(node),
    2695          447 :             NodeType::ENUM_SQL_CHARACTER_TYPE => self.format_character_type_base(node),
    2696          783 :             NodeType::OBJECT_SQL_GENERIC_TYPE => self.format_generic_type(node),
    2697           72 :             NodeType::OBJECT_SQL_TIMESTAMP_TYPE | NodeType::OBJECT_SQL_TIME_TYPE => self.format_timestamp_type(node),
    2698        50708 :             NodeType::OBJECT_SQL_COLUMN_REF => self.format_column_ref(node),
    2699          279 :             NodeType::OBJECT_SQL_PARAMETER_REF => self.format_parameter_ref(node),
    2700           36 :             NodeType::OBJECT_SQL_RELATION_EXPR => self.format_relation_expression(node),
    2701           42 :             NodeType::OBJECT_SQL_DESCRIPTOR => self.format_descriptor(node),
    2702          108 :             NodeType::OBJECT_SQL_INDIRECTION => self.format_indirection(node),
    2703          135 :             NodeType::OBJECT_SQL_ROW_TYPE => self.format_row_type(node),
    2704          258 :             NodeType::OBJECT_SQL_ROW_EXPRESSION => self.format_row_expression(node),
    2705          126 :             NodeType::OBJECT_SQL_ARRAY_EXPRESSION => self.format_array_expression(node),
    2706          780 :             NodeType::OBJECT_SQL_SELECT_EXPRESSION => self.format_select_expression(node),
    2707        20468 :             NodeType::OBJECT_SQL_RESULT_TARGET => self.format_result_target(node),
    2708         1466 :             NodeType::OBJECT_SQL_COLUMN_DEF => self.format_column_def(node),
    2709          219 :             NodeType::ENUM_SQL_TABLE_CONSTRAINT => self.format_table_constraint_type(node),
    2710          219 :             NodeType::OBJECT_SQL_TABLE_CONSTRAINT => self.format_table_constraint(node),
    2711           12 :             NodeType::ENUM_SQL_KEY_MATCH => self.format_key_match(node),
    2712           21 :             NodeType::ENUM_SQL_KEY_ACTION_COMMAND => self.format_key_action_command(node),
    2713           21 :             NodeType::ENUM_SQL_KEY_ACTION_TRIGGER => self.format_key_action_trigger(node),
    2714           21 :             NodeType::OBJECT_SQL_KEY_ACTION => self.format_key_action(node),
    2715          810 :             NodeType::ENUM_SQL_COLUMN_CONSTRAINT => self.format_column_constraint_type(node),
    2716          810 :             NodeType::OBJECT_SQL_COLUMN_CONSTRAINT => self.format_column_constraint(node),
    2717           75 :             NodeType::ENUM_SQL_CONSTRAINT_ATTRIBUTE => self.format_constraint_attribute(node),
    2718           81 :             NodeType::ENUM_SQL_EXTRACT_TARGET => self.format_extract_target(node),
    2719           66 :             NodeType::ENUM_SQL_TRIM_TARGET => self.format_trim_direction(node),
    2720          312 :             NodeType::OBJECT_SQL_GENERIC_OPTION => self.format_generic_option(node),
    2721          108 :             NodeType::OBJECT_SQL_ALIAS => self.format_alias(node),
    2722          141 :             NodeType::OBJECT_SQL_TYPECAST_EXPRESSION => self.format_typecast_expression(node),
    2723         1248 :             NodeType::OBJECT_SQL_CASE => self.format_case(node),
    2724         1278 :             NodeType::OBJECT_SQL_CASE_CLAUSE => self.format_case_clause(node),
    2725          180 :             NodeType::OBJECT_SQL_EXISTS_EXPRESSION => self.format_exists_expression(node),
    2726           99 :             NodeType::OBJECT_SQL_SUBQUERY_EXPRESSION => self.format_subquery_expression(node),
    2727           99 :             NodeType::ENUM_SQL_SUBQUERY_QUANTIFIER => self.format_subquery_quantifier(node),
    2728           93 :             NodeType::OBJECT_SQL_INDIRECTION_INDEX => self.format_indirection_index(node),
    2729           18 :             NodeType::OBJECT_SQL_TYPETEST_EXPRESSION => self.format_typetest_expression(node),
    2730           60 :             NodeType::OBJECT_SQL_ROWSFROM_ITEM => self.format_rows_from_item(node),
    2731           30 :             NodeType::OBJECT_SQL_BIT_TYPE => self.format_bit_type(node),
    2732           12 :             NodeType::OBJECT_SQL_DEF_ARG => self.format_definition_arg(node),
    2733          840 :             NodeType::OBJECT_SQL_CTE => self.format_cte(node),
    2734           90 :             NodeType::OBJECT_SQL_PROPERTY_GRAPH => self.format_property_graph(node),
    2735          135 :             NodeType::OBJECT_SQL_GRAPH_ELEMENT_TABLE => self.format_graph_element_table(node),
    2736           96 :             NodeType::OBJECT_SQL_GRAPH_VERTEX_REFERENCE => self.format_graph_vertex_reference(node),
    2737          138 :             NodeType::OBJECT_SQL_GRAPH_LABEL => self.format_graph_label(node),
    2738          138 :             NodeType::OBJECT_SQL_GRAPH_PROPERTIES => self.format_graph_properties(node),
    2739           78 :             NodeType::OBJECT_SQL_GRAPH_PROPERTY => self.format_graph_property(node),
    2740          105 :             NodeType::OBJECT_SQL_GRAPH_TABLE => self.format_graph_table(node),
    2741          105 :             NodeType::OBJECT_SQL_GRAPH_MATCH => self.format_graph_match(node),
    2742          318 :             NodeType::OBJECT_SQL_GRAPH_PATH_ELEMENT => self.format_graph_path_element(node),
    2743           21 :             NodeType::OBJECT_SQL_GRAPH_QUANTIFIER => self.format_graph_quantifier(node),
    2744          288 :             NodeType::OBJECT_SQL_GRAPH_LABEL_EXPRESSION => self.format_graph_label_expression(node),
    2745           18 :             NodeType::OBJECT_SQL_GRAPH_ROWS => self.format_graph_rows(node),
    2746         8187 :             NodeType::OBJECT_SQL_FUNCTION_EXPRESSION => self.format_function_expression(node),
    2747              :             NodeType::OBJECT_SQL_FUNCTION_CAST_ARGS
    2748              :             | NodeType::OBJECT_SQL_FUNCTION_EXTRACT_ARGS
    2749              :             | NodeType::OBJECT_SQL_FUNCTION_OVERLAY_ARGS
    2750              :             | NodeType::OBJECT_SQL_FUNCTION_POSITION_ARGS
    2751              :             | NodeType::OBJECT_SQL_FUNCTION_SUBSTRING_ARGS
    2752              :             | NodeType::OBJECT_SQL_FUNCTION_TREAT_ARGS
    2753         1437 :             | NodeType::OBJECT_SQL_FUNCTION_TRIM_ARGS => f.empty(),
    2754         2172 :             NodeType::ENUM_SQL_KNOWN_FUNCTION => f.empty(),
    2755          150 :             NodeType::OBJECT_SQL_FUNCTION_TABLE => self.format_function_table(node),
    2756          438 :             NodeType::OBJECT_SQL_WINDOW_FRAME => self.format_window_frame(node),
    2757          222 :             NodeType::OBJECT_SQL_WINDOW_BOUND => self.format_window_bound(node),
    2758          222 :             NodeType::ENUM_SQL_WINDOW_BOUND_MODE => self.format_window_bound_mode(node),
    2759          138 :             NodeType::ENUM_SQL_WINDOW_BOUND_DIRECTION => self.format_window_bound_direction(node),
    2760          126 :             NodeType::ENUM_SQL_WINDOW_RANGE_MODE => self.format_window_range_mode(node),
    2761         5787 :             NodeType::OBJECT_SQL_FUNCTION_ARG => self.format_function_arg(node),
    2762           25 :             NodeType::OBJECT_SQL_CONST_TYPE_CAST => self.format_const_type_cast(node),
    2763          173 :             NodeType::OBJECT_SQL_CONST_INTERVAL_CAST => self.format_const_interval_cast(node),
    2764          343 :             NodeType::OBJECT_SQL_CONST_FUNCTION_CAST => self.format_const_function_cast(node),
    2765        27097 :             NodeType::ENUM_SQL_EXPRESSION_OPERATOR => self.format_expression_operator_type(node),
    2766        27130 :             NodeType::OBJECT_SQL_NARY_EXPRESSION => self.format_expression(node_id),
    2767            9 :             NodeType::OBJECT_EXT_VARARG_ARRAY => self.format_vararg_array(node),
    2768              :             NodeType::LITERAL_NULL
    2769              :             | NodeType::LITERAL_INTEGER
    2770              :             | NodeType::LITERAL_FLOAT
    2771              :             | NodeType::LITERAL_STRING
    2772              :             | NodeType::LITERAL_INTERVAL
    2773              :             | NodeType::BOOL
    2774              :             | NodeType::OPERATOR
    2775       126685 :             | NodeType::NAME => self.format_leaf(node),
    2776            0 :             _ => self.format_unimplemented(node),
    2777              :         }
    2778       458383 :     }
    2779              : 
    2780         5668 :     fn build_docs(&mut self) {
    2781       458383 :         for node_id in 0..self.ast.len() {
    2782       458383 :             let reg = self.format_node(node_id);
    2783       458383 :             self.node_states[node_id].reg = reg;
    2784       458383 :         }
    2785         5668 :     }
    2786              : 
    2787              :     // -----------------------------------------------------------------------------------------
    2788              :     // Output
    2789              :     // -----------------------------------------------------------------------------------------
    2790              : 
    2791         5668 :     fn render_options(&self) -> FormattingRenderOptions {
    2792         5668 :         FormattingRenderOptions {
    2793         5668 :             max_width: self.config.max_width as usize,
    2794         5668 :             indentation_width: self.config.indentation_width as usize,
    2795         5668 :             debug_mode: self.config.debug_mode,
    2796         5668 :             mode: self.config.mode,
    2797         5668 :             keyword_case: self.config.keyword_case,
    2798         5668 :         }
    2799         5668 :     }
    2800              : 
    2801          338 :     fn render(&self, reg: FmtReg) -> String {
    2802          338 :         self.fmt.render(reg, &self.render_options())
    2803          338 :     }
    2804              : 
    2805              :     /// The parts of the script in text order.
    2806              :     ///
    2807              :     /// The parser recovers from syntax errors by dropping the broken statement or by keeping a partial one.
    2808              :     /// Formatting these would silently remove or truncate what the user wrote, so every statement (the text up
    2809              :     /// to the next semicolon) with a scanner or parser error is copied as written.
    2810         5330 :     fn output_parts(&self) -> Vec<OutputPart> {
    2811              :         use dashql_parser::symbol_kind::{S_SEMICOLON, S_YYEOF};
    2812         5330 :         let symbols = &self.scanned.symbols;
    2813         5330 :         let statements = &self.parsed.statements;
    2814         5330 :         let mut parts = Vec::with_capacity(statements.len());
    2815              : 
    2816              :         // The symbol index ranges of the statements, each ends with a semicolon
    2817         5330 :         let mut chunks: Vec<(usize, usize)> = Vec::new();
    2818         5330 :         let mut begin = 0;
    2819       310644 :         for (i, symbol) in symbols.iter().enumerate() {
    2820       310644 :             if symbol.kind == S_SEMICOLON || symbol.kind == S_YYEOF {
    2821         7939 :                 if i > begin || symbol.kind == S_SEMICOLON {
    2822         5512 :                     chunks.push((begin, if symbol.kind == S_SEMICOLON { i + 1 } else { i }));
    2823         2427 :                 }
    2824         7939 :                 begin = i + 1;
    2825       302705 :             }
    2826              :         }
    2827         5330 :         let chunk_of_symbol = |symbol: usize| chunks.iter().position(|&(b, e)| symbol >= b && symbol < e);
    2828         5330 :         let mut damaged = vec![false; chunks.len()];
    2829         5330 :         for error in &self.parsed.errors {
    2830           30 :             let symbol = (error.location.offset() as usize).min(symbols.len().saturating_sub(1));
    2831           30 :             if let Some(chunk) = chunk_of_symbol(symbol).or(chunks.len().checked_sub(1)) {
    2832           30 :                 damaged[chunk] = true;
    2833           30 :             }
    2834              :         }
    2835         5330 :         for error in &self.scanned.errors {
    2836            3 :             let offset = error.location.offset;
    2837           12 :             let symbol = symbols.partition_point(|s| s.location.end() <= offset);
    2838            3 :             if let Some(chunk) = chunk_of_symbol(symbol).or(chunks.len().checked_sub(1)) {
    2839            3 :                 damaged[chunk] = true;
    2840            3 :             }
    2841              :         }
    2842              : 
    2843         5330 :         let mut next_statement = 0;
    2844         5512 :         for (chunk, &(begin, end)) in chunks.iter().enumerate() {
    2845         5512 :             let chunk_symbols = &symbols[begin..end];
    2846         5512 :             let begin_offset = chunk_symbols.first().map_or(0, |s| s.location.offset);
    2847              :             // The last statement may end in text that the scanner dropped, like an unterminated string
    2848         5512 :             let end_offset = match chunk_symbols.last() {
    2849         5512 :                 Some(last) if last.kind == S_SEMICOLON => last.location.end(),
    2850         2903 :                 _ => self.scanned.text.trim_end().len() as u32,
    2851              :             };
    2852         5512 :             let mut in_chunk = Vec::new();
    2853        10994 :             while next_statement < statements.len() {
    2854         5658 :                 let root = self.ast[statements[next_statement].root as usize];
    2855         5658 :                 let root_offset = resolve_text_span(&self.scanned.text, symbols, *root.symbol_span()).offset;
    2856         5658 :                 if root_offset >= end_offset {
    2857          176 :                     break;
    2858         5482 :                 }
    2859         5482 :                 in_chunk.push(next_statement);
    2860         5482 :                 next_statement += 1;
    2861              :             }
    2862         5512 :             let only_separator = chunk_symbols.len() == 1 && chunk_symbols[0].kind == S_SEMICOLON;
    2863         5512 :             if !damaged[chunk] && (!in_chunk.is_empty() || only_separator) {
    2864         5476 :                 parts.extend(in_chunk.into_iter().map(OutputPart::Statement));
    2865         5476 :             } else if !only_separator {
    2866           36 :                 parts.push(OutputPart::Damaged(TextSpan::new(begin_offset, end_offset - begin_offset)));
    2867           36 :             }
    2868              :         }
    2869         5330 :         parts
    2870         5330 :     }
    2871              : 
    2872         5330 :     fn write_output(&self) -> Vec<u8> {
    2873         5330 :         let options = self.render_options();
    2874         5330 :         let statements = &self.parsed.statements;
    2875         5330 :         let parts = self.output_parts();
    2876         5330 :         let mut output: Vec<u8> = Vec::with_capacity(self.estimate_formatted_size());
    2877              : 
    2878         5330 :         if self.config.debug_mode {
    2879            0 :             output.extend_from_slice(
    2880            0 :                 format!("/* indentation={}, max_width={} */\n", self.config.indentation_width, self.config.max_width)
    2881            0 :                     .as_bytes(),
    2882            0 :             );
    2883         5330 :         }
    2884              : 
    2885         5330 :         let input = self.scanned.text.as_bytes();
    2886         5330 :         let damaged_text = |span: &TextSpan| &input[span.offset as usize..span.end() as usize];
    2887         5483 :         if parts.iter().any(|p| matches!(p, OutputPart::Damaged(_))) {
    2888           30 :             self.copied_damaged_text.set(true);
    2889         5300 :         }
    2890              : 
    2891         5330 :         if self.config.mode == FormattingMode::INLINE {
    2892         1849 :             for (i, part) in parts.iter().enumerate() {
    2893         1849 :                 match part {
    2894         1835 :                     OutputPart::Statement(statement) => {
    2895         1835 :                         let root = statements[*statement].root as usize;
    2896         1835 :                         output.extend_from_slice(self.fmt.render(self.node_states[root].reg, &options).as_bytes());
    2897         1835 :                         output.push(b';');
    2898         1835 :                     }
    2899           14 :                     OutputPart::Damaged(span) => output.extend_from_slice(damaged_text(span)),
    2900              :                 }
    2901         1849 :                 if i + 1 < parts.len() {
    2902           64 :                     output.extend_from_slice(b"\n\n");
    2903         1785 :                 }
    2904              :             }
    2905         1785 :             return output;
    2906         3545 :         }
    2907              : 
    2908         3545 :         let comments = &self.scanned.comments[..];
    2909         3545 :         let max_width = self.config.max_width as usize;
    2910         3545 :         let descriptions = self.parsed.associate_descriptions();
    2911         3769 :         let ensure_line_break = |output: &mut Vec<u8>| {
    2912         3769 :             if !output.is_empty() && output.last() != Some(&b'\n') {
    2913          277 :                 output.push(b'\n');
    2914         3493 :             }
    2915         3769 :         };
    2916         3545 :         let mut comment_begin = 0;
    2917         3657 :         for (i, part) in parts.iter().enumerate() {
    2918         3657 :             if i > 0 {
    2919          112 :                 ensure_line_break(&mut output);
    2920          112 :                 output.push(b'\n');
    2921         3545 :             }
    2922         3657 :             let statement = match part {
    2923         3635 :                 OutputPart::Statement(statement) => *statement,
    2924           22 :                 OutputPart::Damaged(span) => {
    2925              :                     // Comments inside the damaged text are part of it
    2926           22 :                     let mut before_end = comment_begin;
    2927           25 :                     while before_end < comments.len() && comments[before_end].offset < span.offset {
    2928            3 :                         before_end += 1;
    2929            3 :                     }
    2930           22 :                     comments::append_comments(
    2931           22 :                         &mut output,
    2932           22 :                         input,
    2933           22 :                         &comments[comment_begin..before_end],
    2934           22 :                         max_width,
    2935           22 :                         Some(span.offset as usize),
    2936              :                     );
    2937           22 :                     ensure_line_break(&mut output);
    2938           22 :                     output.extend_from_slice(damaged_text(span));
    2939           22 :                     comment_begin = before_end;
    2940           25 :                     while comment_begin < comments.len() && comments[comment_begin].offset < span.end() {
    2941            3 :                         comment_begin += 1;
    2942            3 :                     }
    2943           22 :                     continue;
    2944              :                 }
    2945              :             };
    2946         3635 :             let root = statements[statement].root as usize;
    2947         3635 :             let description = &descriptions[statement];
    2948         3635 :             let root_span = resolve_text_span(&self.scanned.text, &self.scanned.symbols, *self.ast[root].symbol_span());
    2949         3635 :             let mut before_end = comment_begin;
    2950         4085 :             while before_end < comments.len() && comments[before_end].offset < root_span.offset {
    2951          450 :                 before_end += 1;
    2952          450 :             }
    2953         3635 :             let description_begin = description.description_begin as usize;
    2954         3635 :             if description.description_count > 0 && description_begin >= comment_begin {
    2955          161 :                 let leading_end = description_begin + description.description_count as usize;
    2956          161 :                 comments::append_comments(
    2957          161 :                     &mut output,
    2958          161 :                     input,
    2959          161 :                     &comments[comment_begin..description_begin],
    2960          161 :                     max_width,
    2961          161 :                     Some(comments[description_begin].offset as usize),
    2962          161 :                 );
    2963          161 :                 comments::append_description(
    2964          161 :                     &mut output,
    2965          161 :                     input,
    2966          161 :                     &comments[description_begin..leading_end],
    2967          161 :                     max_width,
    2968          161 :                     Some(root_span.offset as usize),
    2969          161 :                 );
    2970         3474 :             } else {
    2971         3474 :                 comments::append_comments(
    2972         3474 :                     &mut output,
    2973         3474 :                     input,
    2974         3474 :                     &comments[comment_begin..before_end],
    2975         3474 :                     max_width,
    2976         3474 :                     Some(root_span.offset as usize),
    2977         3474 :                 );
    2978         3474 :             }
    2979              : 
    2980         3635 :             ensure_line_break(&mut output);
    2981         3635 :             output.extend_from_slice(self.fmt.render(self.node_states[root].reg, &options).as_bytes());
    2982         3635 :             output.push(b';');
    2983              : 
    2984         3635 :             let statement_end = description.source_span.end() as usize;
    2985         3635 :             let mut within_end = before_end;
    2986         3676 :             while within_end < comments.len() && (comments[within_end].offset as usize) < statement_end {
    2987           41 :                 within_end += 1;
    2988           41 :             }
    2989         3635 :             comments::append_comments(&mut output, input, &comments[before_end..within_end], max_width, None);
    2990         3635 :             comment_begin = within_end;
    2991              :         }
    2992         3545 :         comments::append_comments(&mut output, input, &comments[comment_begin..], max_width, None);
    2993         3545 :         output
    2994         5330 :     }
    2995              : }
    2996              : 
    2997              : /// The formatted output as a string. Wrapped comments may split UTF-8 sequences, they are replaced
    2998              : /// with U+FFFD.
    2999         5322 : fn bytes_to_string(bytes: Vec<u8>) -> String {
    3000         5322 :     match String::from_utf8(bytes) {
    3001         5322 :         Ok(text) => text,
    3002            0 :         Err(e) => String::from_utf8_lossy(e.as_bytes()).into_owned(),
    3003              :     }
    3004         5322 : }
    3005              : 
    3006              : #[cfg(test)]
    3007              : mod tests {
    3008              :     use super::*;
    3009              :     use dashql_parser::parser::parse;
    3010              :     use dashql_parser::scanner::scan;
    3011              :     use std::sync::Arc;
    3012              : 
    3013            7 :     fn format(text: &str, mode: FormattingMode, max_width: u32) -> (String, Vec<u32>) {
    3014            7 :         let parsed = parse(Arc::new(scan(text, 0, 2)));
    3015            7 :         let mut formatter = Formatter::new(&parsed);
    3016            7 :         let mut config = FormattingConfigT::default();
    3017            7 :         config.mode = mode;
    3018            7 :         config.max_width = max_width;
    3019            7 :         config.indentation_width = 2;
    3020            7 :         let out = formatter.format(&config);
    3021            7 :         (out, formatter.unformattable_nodes())
    3022            7 :     }
    3023              : 
    3024              :     #[test]
    3025            1 :     fn formats_select() {
    3026            1 :         let (out, unformattable) = format("SELECT a,b FROM t WHERE a=1 AND b", FormattingMode::COMPACT, 120);
    3027            1 :         assert_eq!(out, "select a, b from t where a = 1 and b;");
    3028            1 :         assert!(unformattable.is_empty());
    3029            1 :         let (out, _) = format("select a, b from t where a = 1", FormattingMode::PRETTY, 120);
    3030            1 :         assert_eq!(out, "select a, b\nfrom t\nwhere a = 1;");
    3031            1 :     }
    3032              : 
    3033              :     #[test]
    3034            1 :     fn adds_parentheses_by_precedence() {
    3035            1 :         let (out, _) = format("select (1 + 2) * 3, 1 + 2 * 3, (a or b) and c", FormattingMode::INLINE, 120);
    3036            1 :         assert_eq!(out, "select (1 + 2) * 3, 1 + 2 * 3, (a or b) and c;");
    3037            1 :     }
    3038              : 
    3039              :     #[test]
    3040            1 :     fn copies_statements_with_syntax_errors() {
    3041            1 :         let (out, unformattable) = format("select  1; selec  1; select  2", FormattingMode::INLINE, 120);
    3042            1 :         assert_eq!(out, "select 1;\n\nselec  1;\n\nselect 2;");
    3043            1 :         assert!(unformattable.is_empty());
    3044              :         // Comments inside the copied text stay, the comments around it are formatted
    3045            1 :         let (out, _) = format("-- a\nselect from /* b */ from;\n-- c\nselect  2", FormattingMode::COMPACT, 120);
    3046            1 :         assert_eq!(out, "-- a\nselect from /* b */ from;\n\n-- c\nselect 2;");
    3047              :         // A script that is nothing but an error is copied
    3048            1 :         assert_eq!(format("select from where", FormattingMode::PRETTY, 120).0, "select from where");
    3049            1 :     }
    3050              : 
    3051              :     #[test]
    3052            1 :     fn keeps_comments() {
    3053            1 :         let (out, _) = format("-- head\nselect 1; -- tail\nselect 2", FormattingMode::COMPACT, 120);
    3054            1 :         assert_eq!(out, "-- head\nselect 1;\n-- tail\n\nselect 2;");
    3055            1 :     }
    3056              : 
    3057              :     #[test]
    3058            1 :     fn records_unformattable_nodes() {
    3059              :         // CREATE TABLE is only formatted as statement root, format_node_at does not mark the roots
    3060            1 :         let parsed = parse(Arc::new(scan("create table t (a int)", 0, 2)));
    3061            1 :         let root = parsed.statements[0].root as usize;
    3062            1 :         let mut formatter = Formatter::new(&parsed);
    3063            1 :         let mut config = FormattingConfigT::default();
    3064            1 :         config.mode = FormattingMode::INLINE;
    3065            1 :         assert_eq!(formatter.format(&config), "create table t (a integer);");
    3066            1 :         assert!(formatter.is_fully_formatted());
    3067            1 :         assert_eq!(formatter.format_node_at(root, &config), "'<OBJECT_SQL_CREATE>'");
    3068            1 :         assert_eq!(formatter.unformattable_nodes(), vec![root as u32]);
    3069            1 :         assert_eq!(formatter.format_node_at(parsed.nodes.len(), &config), "");
    3070            1 :     }
    3071              : 
    3072              :     #[test]
    3073            1 :     fn looks_up_attributes_like_cxx() {
    3074            3 :         let node = |key: AttributeKey| Node::new(&SymbolSpan::default(), NodeType::NAME, key, 3, 0, 0);
    3075            1 :         let nodes = vec![
    3076            1 :             node(K::SQL_ALIAS_NAME),
    3077            1 :             node(K::SQL_ALIAS_NAME),
    3078            1 :             node(K::SQL_ALIAS_COLUMN_NAMES),
    3079            1 :             Node::new(&SymbolSpan::default(), NodeType::OBJECT_SQL_ALIAS, K::NONE, u32::MAX, 0, 3),
    3080              :         ];
    3081            1 :         let mut parsed = parse(Arc::new(scan("", 0, 2)));
    3082            1 :         parsed.nodes = nodes;
    3083            1 :         parsed.statements.clear();
    3084            1 :         let formatter = Formatter::new(&parsed);
    3085            1 :         let object = &parsed.nodes[3];
    3086              :         // One key: the first match, several keys: the last match
    3087            1 :         let [first] = formatter.attrs(object, [K::SQL_ALIAS_NAME]);
    3088            1 :         assert_eq!(formatter.node_id(first.unwrap()), 0);
    3089            1 :         let [last, columns, missing] =
    3090            1 :             formatter.attrs(object, [K::SQL_ALIAS_NAME, K::SQL_ALIAS_COLUMN_NAMES, K::SQL_ALIAS_COLUMN_DEFS]);
    3091            1 :         assert_eq!(formatter.node_id(last.unwrap()), 1);
    3092            1 :         assert_eq!(formatter.node_id(columns.unwrap()), 2);
    3093            1 :         assert!(missing.is_none());
    3094            1 :     }
    3095              : }
        

Generated by: LCOV version 2.0-1