github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/pretty.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tree
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"strconv"
    17  	"strings"
    18  
    19  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree/treecmp"
    20  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree/treewindow"
    21  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/types"
    22  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/json"
    23  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/pretty"
    24  	"github.com/cockroachdb/errors"
    25  )
    26  
    27  // This file contains methods that convert statements to pretty Docs (a tree
    28  // structure that can be pretty printed at a specific line width). Nodes
    29  // implement the docer interface to allow this conversion. In general,
    30  // a node implements doc by copying its Format method and returning a Doc
    31  // structure instead of writing to a buffer. Some guidelines are below.
    32  //
    33  // Nodes should not precede themselves with a space. Instead, the parent
    34  // structure should correctly add spaces when needed.
    35  //
    36  // nestName should be used for most `KEYWORD <expr>` constructs.
    37  //
    38  // Nodes that never need to line break or for which the Format method already
    39  // produces a compact representation should not implement doc, but instead
    40  // rely on the default fallback that uses .Format. Examples include datums
    41  // and constants.
    42  
    43  // PrettyCfg holds configuration for pretty printing statements.
    44  type PrettyCfg struct {
    45  	// LineWidth is the desired maximum line width.
    46  	LineWidth int
    47  	// TabWidth is the amount of spaces to use for tabs when UseTabs is
    48  	// false.
    49  	TabWidth int
    50  	// DoNotNewLineAfterColName is true if we do not new line after table column names.
    51  	DoNotNewLineAfterColName bool
    52  	// Align, when set to another value than PrettyNoAlign, uses
    53  	// alignment for some constructs as a first choice. If not set or if
    54  	// the line width is insufficient, nesting is used instead.
    55  	Align PrettyAlignMode
    56  	// UseTabs indicates whether to use tab chars to signal indentation.
    57  	UseTabs bool
    58  	// Simplify, when set, removes extraneous parentheses.
    59  	Simplify bool
    60  	// Case, if set, transforms case-insensitive strings (like SQL keywords).
    61  	Case func(string) string
    62  	// JSONFmt, when set, pretty-prints strings that are asserted or cast
    63  	// to JSON.
    64  	JSONFmt bool
    65  	// ValueRedaction, when set, surrounds literal values with redaction markers.
    66  	ValueRedaction bool
    67  }
    68  
    69  // DefaultPrettyCfg returns a PrettyCfg with the default
    70  // configuration.
    71  func DefaultPrettyCfg() PrettyCfg {
    72  	return PrettyCfg{
    73  		LineWidth: DefaultLineWidth,
    74  		Simplify:  true,
    75  		TabWidth:  4,
    76  		UseTabs:   true,
    77  		Align:     PrettyNoAlign, // TODO(knz): I really want this to be AlignAndDeindent
    78  	}
    79  }
    80  
    81  // PrettyAlignMode directs which alignment mode to use.
    82  //
    83  // TODO(knz/mjibson): this variety of options currently exists so as
    84  // to enable comparisons and gauging individual preferences. We should
    85  // aim to remove some or all of these options in the future.
    86  type PrettyAlignMode int
    87  
    88  const (
    89  	// PrettyNoAlign disables alignment.
    90  	PrettyNoAlign PrettyAlignMode = 0
    91  	// PrettyAlignOnly aligns sub-clauses only and preserves the
    92  	// hierarchy of logical operators.
    93  	PrettyAlignOnly = 1
    94  	// PrettyAlignAndDeindent does the work of PrettyAlignOnly and also
    95  	// de-indents AND and OR operators.
    96  	PrettyAlignAndDeindent = 2
    97  	// PrettyAlignAndExtraIndent does the work of PrettyAlignOnly and
    98  	// also extra indents the operands of AND and OR operators so
    99  	// that they appear aligned but also indented.
   100  	PrettyAlignAndExtraIndent = 3
   101  )
   102  
   103  // CaseMode directs which casing mode to use.
   104  type CaseMode int
   105  
   106  const (
   107  	// LowerCase transforms case-insensitive strings (like SQL keywords) to lowercase.
   108  	LowerCase CaseMode = 0
   109  	// UpperCase transforms case-insensitive strings (like SQL keywords) to uppercase.
   110  	UpperCase CaseMode = 1
   111  )
   112  
   113  // LineWidthMode directs which mode of line width to use.
   114  type LineWidthMode int
   115  
   116  const (
   117  	// DefaultLineWidth is the line width used with the default pretty-printing configuration.
   118  	DefaultLineWidth = 60
   119  	// ConsoleLineWidth is the line width used on the frontend console.
   120  	ConsoleLineWidth = 108
   121  )
   122  
   123  // keywordWithText returns a pretty.Keyword with left and/or right
   124  // sides concat'd as a pretty.Text.
   125  func (p *PrettyCfg) keywordWithText(left, keyword, right string) pretty.Doc {
   126  	doc := pretty.Keyword(keyword)
   127  	if left != "" {
   128  		doc = pretty.Concat(pretty.Text(left), doc)
   129  	}
   130  	if right != "" {
   131  		doc = pretty.Concat(doc, pretty.Text(right))
   132  	}
   133  	return doc
   134  }
   135  
   136  func (p *PrettyCfg) bracket(l string, d pretty.Doc, r string) pretty.Doc {
   137  	return p.bracketDoc(pretty.Text(l), d, pretty.Text(r))
   138  }
   139  
   140  func (p *PrettyCfg) bracketDoc(l, d, r pretty.Doc) pretty.Doc {
   141  	return pretty.BracketDoc(l, d, r)
   142  }
   143  
   144  func (p *PrettyCfg) bracketKeyword(
   145  	leftKeyword, leftParen string, inner pretty.Doc, rightParen, rightKeyword string,
   146  ) pretty.Doc {
   147  	var left, right pretty.Doc
   148  	if leftKeyword != "" {
   149  		left = p.keywordWithText("", leftKeyword, leftParen)
   150  	} else {
   151  		left = pretty.Text(leftParen)
   152  	}
   153  	if rightKeyword != "" {
   154  		right = p.keywordWithText(rightParen, rightKeyword, "")
   155  	} else {
   156  		right = pretty.Text(rightParen)
   157  	}
   158  	return p.bracketDoc(left, inner, right)
   159  }
   160  
   161  // Pretty pretty prints stmt with default options.
   162  func Pretty(stmt NodeFormatter) (string, error) {
   163  	cfg := DefaultPrettyCfg()
   164  	return cfg.Pretty(stmt)
   165  }
   166  
   167  // Pretty pretty prints stmt with specified options.
   168  func (p *PrettyCfg) Pretty(stmt NodeFormatter) (string, error) {
   169  	doc := p.Doc(stmt)
   170  	return pretty.Pretty(doc, p.LineWidth, p.UseTabs, p.TabWidth, p.Case)
   171  }
   172  
   173  // Doc converts f (generally a Statement) to a pretty.Doc. If f does not have a
   174  // native conversion, its .Format representation is used as a simple Text Doc.
   175  func (p *PrettyCfg) Doc(f NodeFormatter) pretty.Doc {
   176  	if f, ok := f.(docer); ok {
   177  		doc := f.doc(p)
   178  		return doc
   179  	}
   180  	return p.docAsString(f)
   181  }
   182  
   183  func (p *PrettyCfg) docAsString(f NodeFormatter) pretty.Doc {
   184  	txt := AsStringWithFlags(f, p.fmtFlags())
   185  	return pretty.Text(strings.TrimSpace(txt))
   186  }
   187  
   188  func (p *PrettyCfg) fmtFlags() FmtFlags {
   189  	prettyFlags := FmtShowPasswords | FmtParsable | FmtTagDollarQuotes
   190  	if p.ValueRedaction {
   191  		prettyFlags |= FmtMarkRedactionNode | FmtOmitNameRedaction
   192  	}
   193  	return prettyFlags
   194  }
   195  
   196  func (p *PrettyCfg) nestUnder(a, b pretty.Doc) pretty.Doc {
   197  	if p.Align != PrettyNoAlign {
   198  		return pretty.AlignUnder(a, b)
   199  	}
   200  	return pretty.NestUnder(a, b)
   201  }
   202  
   203  // rlTable produces a Table using Right alignment of the first column.
   204  func (p *PrettyCfg) rlTable(rows ...pretty.TableRow) pretty.Doc {
   205  	alignment := pretty.TableNoAlign
   206  	if p.Align != PrettyNoAlign {
   207  		alignment = pretty.TableRightAlignFirstColumn
   208  	}
   209  	return pretty.Table(alignment, pretty.Keyword, p.DoNotNewLineAfterColName, rows...)
   210  }
   211  
   212  // llTable produces a Table using Left alignment of the first column.
   213  func (p *PrettyCfg) llTable(docFn func(string) pretty.Doc, rows ...pretty.TableRow) pretty.Doc {
   214  	alignment := pretty.TableNoAlign
   215  	if p.Align != PrettyNoAlign {
   216  		alignment = pretty.TableLeftAlignFirstColumn
   217  	}
   218  	return pretty.Table(alignment, docFn, p.DoNotNewLineAfterColName, rows...)
   219  }
   220  
   221  func (p *PrettyCfg) row(lbl string, d pretty.Doc) pretty.TableRow {
   222  	return pretty.TableRow{Label: lbl, Doc: d}
   223  }
   224  
   225  var emptyRow = pretty.TableRow{}
   226  
   227  func (p *PrettyCfg) unrow(r pretty.TableRow) pretty.Doc {
   228  	if r.Doc == nil {
   229  		return pretty.Nil
   230  	}
   231  	if r.Label == "" {
   232  		return r.Doc
   233  	}
   234  	return p.nestUnder(pretty.Text(r.Label), r.Doc)
   235  }
   236  
   237  func (p *PrettyCfg) commaSeparated(d ...pretty.Doc) pretty.Doc {
   238  	return pretty.Join(",", d...)
   239  }
   240  
   241  func (p *PrettyCfg) joinNestedOuter(lbl string, d ...pretty.Doc) pretty.Doc {
   242  	if len(d) == 0 {
   243  		return pretty.Nil
   244  	}
   245  	switch p.Align {
   246  	case PrettyAlignAndDeindent:
   247  		return pretty.JoinNestedOuter(lbl, pretty.Keyword, d...)
   248  	case PrettyAlignAndExtraIndent:
   249  		items := make([]pretty.TableRow, len(d))
   250  		for i, dd := range d {
   251  			if i > 0 {
   252  				items[i].Label = lbl
   253  			}
   254  			items[i].Doc = dd
   255  		}
   256  		return pretty.Table(pretty.TableRightAlignFirstColumn, pretty.Keyword, p.DoNotNewLineAfterColName, items...)
   257  	default:
   258  		return pretty.JoinNestedRight(pretty.Keyword(lbl), d...)
   259  	}
   260  }
   261  
   262  // docer is implemented by nodes that can convert themselves into
   263  // pretty.Docs. If nodes cannot, node.Format is used instead as a Text Doc.
   264  type docer interface {
   265  	doc(*PrettyCfg) pretty.Doc
   266  }
   267  
   268  // tableDocer is implemented by nodes that can convert themselves
   269  // into []pretty.TableRow, i.e. a table.
   270  type tableDocer interface {
   271  	docTable(*PrettyCfg) []pretty.TableRow
   272  }
   273  
   274  func (node SelectExprs) doc(p *PrettyCfg) pretty.Doc {
   275  	d := make([]pretty.Doc, len(node))
   276  	for i, e := range node {
   277  		d[i] = e.doc(p)
   278  	}
   279  	return p.commaSeparated(d...)
   280  }
   281  
   282  func (node SelectExpr) doc(p *PrettyCfg) pretty.Doc {
   283  	e := node.Expr
   284  	if p.Simplify {
   285  		e = StripParens(e)
   286  	}
   287  	d := p.Doc(e)
   288  	if node.As != "" {
   289  		d = p.nestUnder(
   290  			d,
   291  			pretty.Concat(p.keywordWithText("", "AS", " "), p.Doc(&node.As)),
   292  		)
   293  	}
   294  	return d
   295  }
   296  
   297  func (node TableExprs) doc(p *PrettyCfg) pretty.Doc {
   298  	if len(node) == 0 {
   299  		return pretty.Nil
   300  	}
   301  	d := make([]pretty.Doc, len(node))
   302  	for i, e := range node {
   303  		if p.Simplify {
   304  			e = StripTableParens(e)
   305  		}
   306  		d[i] = p.Doc(e)
   307  	}
   308  	return p.commaSeparated(d...)
   309  }
   310  
   311  func (node *Where) doc(p *PrettyCfg) pretty.Doc {
   312  	return p.unrow(node.docRow(p))
   313  }
   314  
   315  func (node *Where) docRow(p *PrettyCfg) pretty.TableRow {
   316  	if node == nil {
   317  		return emptyRow
   318  	}
   319  	e := node.Expr
   320  	if p.Simplify {
   321  		e = StripParens(e)
   322  	}
   323  	return p.row(node.Type, p.Doc(e))
   324  }
   325  
   326  func (node *GroupBy) doc(p *PrettyCfg) pretty.Doc {
   327  	return p.unrow(node.docRow(p))
   328  }
   329  
   330  func (node *GroupBy) docRow(p *PrettyCfg) pretty.TableRow {
   331  	if len(*node) == 0 {
   332  		return emptyRow
   333  	}
   334  	d := make([]pretty.Doc, len(*node))
   335  	for i, e := range *node {
   336  		// Beware! The GROUP BY items should never be simplified by
   337  		// stripping parentheses, because parentheses there are
   338  		// semantically important.
   339  		d[i] = p.Doc(e)
   340  	}
   341  	return p.row("GROUP BY", p.commaSeparated(d...))
   342  }
   343  
   344  // flattenOp populates a slice with all the leaves operands of an expression
   345  // tree where all the nodes satisfy the given predicate.
   346  func (p *PrettyCfg) flattenOp(
   347  	e Expr,
   348  	pred func(e Expr, recurse func(e Expr)) bool,
   349  	formatOperand func(e Expr) pretty.Doc,
   350  	in []pretty.Doc,
   351  ) []pretty.Doc {
   352  	if ok := pred(e, func(sub Expr) {
   353  		in = p.flattenOp(sub, pred, formatOperand, in)
   354  	}); ok {
   355  		return in
   356  	}
   357  	return append(in, formatOperand(e))
   358  }
   359  
   360  func (p *PrettyCfg) peelAndOrOperand(e Expr) Expr {
   361  	if !p.Simplify {
   362  		return e
   363  	}
   364  	stripped := StripParens(e)
   365  	switch stripped.(type) {
   366  	case *BinaryExpr, *ComparisonExpr, *RangeCond, *FuncExpr, *IndirectionExpr,
   367  		*UnaryExpr, *AnnotateTypeExpr, *CastExpr, *ColumnItem, *UnresolvedName:
   368  		// All these expressions have higher precedence than binary
   369  		// expressions.
   370  		return stripped
   371  	}
   372  	// Everything else - we don't know. Be conservative and keep the
   373  	// original form.
   374  	return e
   375  }
   376  
   377  func (node *AndExpr) doc(p *PrettyCfg) pretty.Doc {
   378  	pred := func(e Expr, recurse func(e Expr)) bool {
   379  		if a, ok := e.(*AndExpr); ok {
   380  			recurse(a.Left)
   381  			recurse(a.Right)
   382  			return true
   383  		}
   384  		return false
   385  	}
   386  	formatOperand := func(e Expr) pretty.Doc {
   387  		return p.Doc(p.peelAndOrOperand(e))
   388  	}
   389  	operands := p.flattenOp(node.Left, pred, formatOperand, nil)
   390  	operands = p.flattenOp(node.Right, pred, formatOperand, operands)
   391  	return p.joinNestedOuter("AND", operands...)
   392  }
   393  
   394  func (node *OrExpr) doc(p *PrettyCfg) pretty.Doc {
   395  	pred := func(e Expr, recurse func(e Expr)) bool {
   396  		if a, ok := e.(*OrExpr); ok {
   397  			recurse(a.Left)
   398  			recurse(a.Right)
   399  			return true
   400  		}
   401  		return false
   402  	}
   403  	formatOperand := func(e Expr) pretty.Doc {
   404  		return p.Doc(p.peelAndOrOperand(e))
   405  	}
   406  	operands := p.flattenOp(node.Left, pred, formatOperand, nil)
   407  	operands = p.flattenOp(node.Right, pred, formatOperand, operands)
   408  	return p.joinNestedOuter("OR", operands...)
   409  }
   410  
   411  func (node *Exprs) doc(p *PrettyCfg) pretty.Doc {
   412  	if node == nil || len(*node) == 0 {
   413  		return pretty.Nil
   414  	}
   415  	d := make([]pretty.Doc, len(*node))
   416  	for i, e := range *node {
   417  		if p.Simplify {
   418  			e = StripParens(e)
   419  		}
   420  		d[i] = p.Doc(e)
   421  	}
   422  	return p.commaSeparated(d...)
   423  }
   424  
   425  // peelBinaryOperand conditionally (p.Simplify) removes the
   426  // parentheses around an expression. The parentheses are always
   427  // removed in the following conditions:
   428  //   - if the operand is a unary operator (these are always
   429  //     of higher precedence): "(-a) * b" -> "-a * b"
   430  //   - if the operand is a binary operator and its precedence
   431  //     is guaranteed to be higher: "(a * b) + c" -> "a * b + c"
   432  //
   433  // Additionally, iff sameLevel is set, then parentheses are removed
   434  // around any binary operator that has the same precedence level as
   435  // the parent.
   436  // sameLevel can be set:
   437  //
   438  //   - for the left operand of all binary expressions, because
   439  //     (in pg SQL) all binary expressions are left-associative.
   440  //     This rewrites e.g. "(a + b) - c" -> "a + b - c"
   441  //     and "(a - b) + c" -> "a - b + c"
   442  //   - for the right operand when the parent operator is known
   443  //     to be fully associative, e.g.
   444  //     "a + (b - c)" -> "a + b - c" because "+" is fully assoc,
   445  //     but "a - (b + c)" cannot be simplified because "-" is not fully associative.
   446  func (p *PrettyCfg) peelBinaryOperand(e Expr, sameLevel bool, parenPrio int) Expr {
   447  	if !p.Simplify {
   448  		return e
   449  	}
   450  	stripped := StripParens(e)
   451  	switch te := stripped.(type) {
   452  	case *BinaryExpr:
   453  		// Do not fold explicit operators.
   454  		if te.Operator.IsExplicitOperator {
   455  			return e
   456  		}
   457  		childPrio := binaryOpPrio[te.Operator.Symbol]
   458  		if childPrio < parenPrio || (sameLevel && childPrio == parenPrio) {
   459  			return stripped
   460  		}
   461  	case *FuncExpr, *UnaryExpr, *AnnotateTypeExpr, *IndirectionExpr,
   462  		*CastExpr, *ColumnItem, *UnresolvedName:
   463  		// All these expressions have higher precedence than binary expressions.
   464  		return stripped
   465  	}
   466  	// Everything else - we don't know. Be conservative and keep the
   467  	// original form.
   468  	return e
   469  }
   470  
   471  func (node *BinaryExpr) doc(p *PrettyCfg) pretty.Doc {
   472  	// All the binary operators are at least left-associative.
   473  	// So we can always simplify "(a OP b) OP c" to "a OP b OP c".
   474  	parenPrio := binaryOpPrio[node.Operator.Symbol]
   475  	leftOperand := p.peelBinaryOperand(node.Left, true /*sameLevel*/, parenPrio)
   476  	// If the binary operator is also fully associative,
   477  	// we can also simplify "a OP (b OP c)" to "a OP b OP c".
   478  	opFullyAssoc := binaryOpFullyAssoc[node.Operator.Symbol]
   479  	rightOperand := p.peelBinaryOperand(node.Right, opFullyAssoc, parenPrio)
   480  
   481  	opDoc := pretty.Text(node.Operator.String())
   482  	var res pretty.Doc
   483  	if !node.Operator.Symbol.IsPadded() {
   484  		res = pretty.JoinDoc(opDoc, p.Doc(leftOperand), p.Doc(rightOperand))
   485  	} else {
   486  		pred := func(e Expr, recurse func(e Expr)) bool {
   487  			if b, ok := e.(*BinaryExpr); ok && b.Operator == node.Operator {
   488  				leftSubOperand := p.peelBinaryOperand(b.Left, true /*sameLevel*/, parenPrio)
   489  				rightSubOperand := p.peelBinaryOperand(b.Right, opFullyAssoc, parenPrio)
   490  				recurse(leftSubOperand)
   491  				recurse(rightSubOperand)
   492  				return true
   493  			}
   494  			return false
   495  		}
   496  		formatOperand := func(e Expr) pretty.Doc {
   497  			return p.Doc(e)
   498  		}
   499  		operands := p.flattenOp(leftOperand, pred, formatOperand, nil)
   500  		operands = p.flattenOp(rightOperand, pred, formatOperand, operands)
   501  		res = pretty.JoinNestedRight(
   502  			opDoc, operands...)
   503  	}
   504  	return pretty.Group(res)
   505  }
   506  
   507  func (node *ParenExpr) doc(p *PrettyCfg) pretty.Doc {
   508  	return p.bracket("(", p.Doc(node.Expr), ")")
   509  }
   510  
   511  func (node *ParenSelect) doc(p *PrettyCfg) pretty.Doc {
   512  	return p.bracket("(", p.Doc(node.Select), ")")
   513  }
   514  
   515  func (node *ParenTableExpr) doc(p *PrettyCfg) pretty.Doc {
   516  	return p.bracket("(", p.Doc(node.Expr), ")")
   517  }
   518  
   519  func (node *Limit) doc(p *PrettyCfg) pretty.Doc {
   520  	res := pretty.Nil
   521  	for i, r := range node.docTable(p) {
   522  		if r.Doc != nil {
   523  			if i > 0 {
   524  				res = pretty.Concat(res, pretty.Line)
   525  			}
   526  			res = pretty.Concat(res, p.nestUnder(pretty.Text(r.Label), r.Doc))
   527  		}
   528  	}
   529  	return res
   530  }
   531  
   532  func (node *Limit) docTable(p *PrettyCfg) []pretty.TableRow {
   533  	if node == nil {
   534  		return nil
   535  	}
   536  	res := make([]pretty.TableRow, 0, 2)
   537  	if node.Count != nil {
   538  		e := node.Count
   539  		if p.Simplify {
   540  			e = StripParens(e)
   541  		}
   542  		res = append(res, p.row("LIMIT", p.Doc(e)))
   543  	} else if node.LimitAll {
   544  		res = append(res, p.row("LIMIT", pretty.Keyword("ALL")))
   545  	}
   546  	if node.Offset != nil {
   547  		e := node.Offset
   548  		if p.Simplify {
   549  			e = StripParens(e)
   550  		}
   551  		res = append(res, p.row("OFFSET", p.Doc(e)))
   552  	}
   553  	return res
   554  }
   555  
   556  func (node *OrderBy) doc(p *PrettyCfg) pretty.Doc {
   557  	return p.unrow(node.docRow(p))
   558  }
   559  
   560  func (node *OrderBy) docRow(p *PrettyCfg) pretty.TableRow {
   561  	if node == nil || len(*node) == 0 {
   562  		return emptyRow
   563  	}
   564  	d := make([]pretty.Doc, len(*node))
   565  	for i, e := range *node {
   566  		// Beware! The ORDER BY items should never be simplified,
   567  		// because parentheses there are semantically important.
   568  		d[i] = p.Doc(e)
   569  	}
   570  	return p.row("ORDER BY", p.commaSeparated(d...))
   571  }
   572  
   573  func (node *Select) doc(p *PrettyCfg) pretty.Doc {
   574  	return p.rlTable(node.docTable(p)...)
   575  }
   576  
   577  func (node *Select) docTable(p *PrettyCfg) []pretty.TableRow {
   578  	items := make([]pretty.TableRow, 0, 9)
   579  	items = append(items, node.With.docRow(p))
   580  	if s, ok := node.Select.(tableDocer); ok {
   581  		items = append(items, s.docTable(p)...)
   582  	} else {
   583  		items = append(items, p.row("", p.Doc(node.Select)))
   584  	}
   585  	items = append(items, node.OrderBy.docRow(p))
   586  	items = append(items, node.Limit.docTable(p)...)
   587  	items = append(items, node.Locking.docTable(p)...)
   588  	return items
   589  }
   590  
   591  func (node *SelectClause) doc(p *PrettyCfg) pretty.Doc {
   592  	return p.rlTable(node.docTable(p)...)
   593  }
   594  
   595  func (node *SelectClause) docTable(p *PrettyCfg) []pretty.TableRow {
   596  	if node.TableSelect {
   597  		return []pretty.TableRow{p.row("TABLE", p.Doc(node.From.Tables[0]))}
   598  	}
   599  	exprs := node.Exprs.doc(p)
   600  	if node.Distinct {
   601  		if node.DistinctOn != nil {
   602  			exprs = pretty.ConcatLine(p.Doc(&node.DistinctOn), exprs)
   603  		} else {
   604  			exprs = pretty.ConcatLine(pretty.Keyword("DISTINCT"), exprs)
   605  		}
   606  	}
   607  	return []pretty.TableRow{
   608  		p.row("SELECT", exprs),
   609  		node.From.docRow(p),
   610  		node.Where.docRow(p),
   611  		node.GroupBy.docRow(p),
   612  		node.Having.docRow(p),
   613  		node.Window.docRow(p),
   614  	}
   615  }
   616  
   617  func (node *From) doc(p *PrettyCfg) pretty.Doc {
   618  	return p.unrow(node.docRow(p))
   619  }
   620  
   621  func (node *From) docRow(p *PrettyCfg) pretty.TableRow {
   622  	if node == nil || len(node.Tables) == 0 {
   623  		return emptyRow
   624  	}
   625  	d := node.Tables.doc(p)
   626  	if node.AsOf.Expr != nil {
   627  		d = p.nestUnder(
   628  			d,
   629  			p.Doc(&node.AsOf),
   630  		)
   631  	}
   632  	return p.row("FROM", d)
   633  }
   634  
   635  func (node *Window) doc(p *PrettyCfg) pretty.Doc {
   636  	return p.unrow(node.docRow(p))
   637  }
   638  
   639  func (node *Window) docRow(p *PrettyCfg) pretty.TableRow {
   640  	if node == nil || len(*node) == 0 {
   641  		return emptyRow
   642  	}
   643  	d := make([]pretty.Doc, len(*node))
   644  	for i, e := range *node {
   645  		d[i] = pretty.Fold(pretty.Concat,
   646  			pretty.Text(e.Name.String()),
   647  			p.keywordWithText(" ", "AS", " "),
   648  			p.Doc(e),
   649  		)
   650  	}
   651  	return p.row("WINDOW", p.commaSeparated(d...))
   652  }
   653  
   654  func (node *With) doc(p *PrettyCfg) pretty.Doc {
   655  	return p.unrow(node.docRow(p))
   656  }
   657  
   658  func (node *With) docRow(p *PrettyCfg) pretty.TableRow {
   659  	if node == nil {
   660  		return emptyRow
   661  	}
   662  	d := make([]pretty.Doc, len(node.CTEList))
   663  	for i, cte := range node.CTEList {
   664  		asString := "AS"
   665  		switch cte.Mtr {
   666  		case CTEMaterializeAlways:
   667  			asString += " MATERIALIZED"
   668  		case CTEMaterializeNever:
   669  			asString += " NOT MATERIALIZED"
   670  		}
   671  		d[i] = p.nestUnder(
   672  			p.Doc(&cte.Name),
   673  			p.bracketKeyword(asString, " (", p.Doc(cte.Stmt), ")", ""),
   674  		)
   675  	}
   676  	kw := "WITH"
   677  	if node.Recursive {
   678  		kw = "WITH RECURSIVE"
   679  	}
   680  	return p.row(kw, p.commaSeparated(d...))
   681  }
   682  
   683  func (node *Subquery) doc(p *PrettyCfg) pretty.Doc {
   684  	d := pretty.Text("<unknown>")
   685  	if node.Select != nil {
   686  		d = p.Doc(node.Select)
   687  	}
   688  	if node.Exists {
   689  		d = pretty.Concat(
   690  			pretty.Keyword("EXISTS"),
   691  			d,
   692  		)
   693  	}
   694  	return d
   695  }
   696  
   697  func (node *AliasedTableExpr) doc(p *PrettyCfg) pretty.Doc {
   698  	d := p.Doc(node.Expr)
   699  	if node.Lateral {
   700  		d = pretty.Concat(
   701  			p.keywordWithText("", "LATERAL", " "),
   702  			d,
   703  		)
   704  	}
   705  	if node.IndexFlags != nil {
   706  		d = pretty.Concat(
   707  			d,
   708  			p.Doc(node.IndexFlags),
   709  		)
   710  	}
   711  	if node.Ordinality {
   712  		d = pretty.Concat(
   713  			d,
   714  			p.keywordWithText(" ", "WITH ORDINALITY", ""),
   715  		)
   716  	}
   717  	if node.As.Alias != "" {
   718  		d = p.nestUnder(
   719  			d,
   720  			pretty.Concat(
   721  				p.keywordWithText("", "AS", " "),
   722  				p.Doc(&node.As),
   723  			),
   724  		)
   725  	}
   726  	return d
   727  }
   728  
   729  func (node *FuncExpr) doc(p *PrettyCfg) pretty.Doc {
   730  	d := p.Doc(&node.Func)
   731  
   732  	if len(node.Exprs) > 0 {
   733  		args := node.Exprs.doc(p)
   734  		if node.Type != 0 {
   735  			args = pretty.ConcatLine(
   736  				pretty.Text(funcTypeName[node.Type]),
   737  				args,
   738  			)
   739  		}
   740  
   741  		if node.AggType == GeneralAgg && len(node.OrderBy) > 0 {
   742  			args = pretty.ConcatSpace(args, node.OrderBy.doc(p))
   743  		}
   744  		d = pretty.Concat(d, p.bracket("(", args, ")"))
   745  	} else {
   746  		d = pretty.Concat(d, pretty.Text("()"))
   747  	}
   748  	if node.AggType == OrderedSetAgg && len(node.OrderBy) > 0 {
   749  		args := node.OrderBy.doc(p)
   750  		d = pretty.Concat(d, p.bracket("WITHIN GROUP (", args, ")"))
   751  	}
   752  	if node.Filter != nil {
   753  		d = pretty.Fold(pretty.ConcatSpace,
   754  			d,
   755  			pretty.Keyword("FILTER"),
   756  			p.bracket("(",
   757  				p.nestUnder(pretty.Keyword("WHERE"), p.Doc(node.Filter)),
   758  				")"))
   759  	}
   760  	if window := node.WindowDef; window != nil {
   761  		var over pretty.Doc
   762  		if window.Name != "" {
   763  			over = p.Doc(&window.Name)
   764  		} else {
   765  			over = p.Doc(window)
   766  		}
   767  		d = pretty.Fold(pretty.ConcatSpace,
   768  			d,
   769  			pretty.Keyword("OVER"),
   770  			over,
   771  		)
   772  	}
   773  	return d
   774  }
   775  
   776  func (node *WindowDef) doc(p *PrettyCfg) pretty.Doc {
   777  	rows := make([]pretty.TableRow, 0, 4)
   778  	if node.RefName != "" {
   779  		rows = append(rows, p.row("", p.Doc(&node.RefName)))
   780  	}
   781  	if len(node.Partitions) > 0 {
   782  		rows = append(rows, p.row("PARTITION BY", p.Doc(&node.Partitions)))
   783  	}
   784  	if len(node.OrderBy) > 0 {
   785  		rows = append(rows, node.OrderBy.docRow(p))
   786  	}
   787  	if node.Frame != nil {
   788  		rows = append(rows, node.Frame.docRow(p))
   789  	}
   790  	if len(rows) == 0 {
   791  		return pretty.Text("()")
   792  	}
   793  	return p.bracket("(", p.rlTable(rows...), ")")
   794  }
   795  
   796  func (wf *WindowFrame) docRow(p *PrettyCfg) pretty.TableRow {
   797  	kw := "RANGE"
   798  	if wf.Mode == treewindow.ROWS {
   799  		kw = "ROWS"
   800  	} else if wf.Mode == treewindow.GROUPS {
   801  		kw = "GROUPS"
   802  	}
   803  	d := p.Doc(wf.Bounds.StartBound)
   804  	if wf.Bounds.EndBound != nil {
   805  		d = p.rlTable(
   806  			p.row("BETWEEN", d),
   807  			p.row("AND", p.Doc(wf.Bounds.EndBound)),
   808  		)
   809  	}
   810  	if wf.Exclusion != treewindow.NoExclusion {
   811  		d = pretty.Stack(d, pretty.Keyword(wf.Exclusion.String()))
   812  	}
   813  	return p.row(kw, d)
   814  }
   815  
   816  func (node *WindowFrameBound) doc(p *PrettyCfg) pretty.Doc {
   817  	switch node.BoundType {
   818  	case treewindow.UnboundedPreceding:
   819  		return pretty.Keyword("UNBOUNDED PRECEDING")
   820  	case treewindow.OffsetPreceding:
   821  		return pretty.ConcatSpace(p.Doc(node.OffsetExpr), pretty.Keyword("PRECEDING"))
   822  	case treewindow.CurrentRow:
   823  		return pretty.Keyword("CURRENT ROW")
   824  	case treewindow.OffsetFollowing:
   825  		return pretty.ConcatSpace(p.Doc(node.OffsetExpr), pretty.Keyword("FOLLOWING"))
   826  	case treewindow.UnboundedFollowing:
   827  		return pretty.Keyword("UNBOUNDED FOLLOWING")
   828  	default:
   829  		panic(errors.AssertionFailedf("unexpected type %d", errors.Safe(node.BoundType)))
   830  	}
   831  }
   832  
   833  func (node *LockingClause) doc(p *PrettyCfg) pretty.Doc {
   834  	return p.rlTable(node.docTable(p)...)
   835  }
   836  
   837  func (node *LockingClause) docTable(p *PrettyCfg) []pretty.TableRow {
   838  	items := make([]pretty.TableRow, len(*node))
   839  	for i, n := range *node {
   840  		items[i] = p.row("", p.Doc(n))
   841  	}
   842  	return items
   843  }
   844  
   845  func (node *LockingItem) doc(p *PrettyCfg) pretty.Doc {
   846  	return p.rlTable(node.docTable(p)...)
   847  }
   848  
   849  func (node *LockingItem) docTable(p *PrettyCfg) []pretty.TableRow {
   850  	if node.Strength == ForNone {
   851  		return nil
   852  	}
   853  	items := make([]pretty.TableRow, 0, 3)
   854  	items = append(items, node.Strength.docTable(p)...)
   855  	if len(node.Targets) > 0 {
   856  		items = append(items, p.row("OF", p.Doc(&node.Targets)))
   857  	}
   858  	items = append(items, node.WaitPolicy.docTable(p)...)
   859  	return items
   860  }
   861  
   862  func (node LockingStrength) doc(p *PrettyCfg) pretty.Doc {
   863  	return p.rlTable(node.docTable(p)...)
   864  }
   865  
   866  func (node LockingStrength) docTable(p *PrettyCfg) []pretty.TableRow {
   867  	str := node.String()
   868  	if str == "" {
   869  		return nil
   870  	}
   871  	return []pretty.TableRow{p.row("", pretty.Keyword(str))}
   872  }
   873  
   874  func (node LockingWaitPolicy) doc(p *PrettyCfg) pretty.Doc {
   875  	return p.rlTable(node.docTable(p)...)
   876  }
   877  
   878  func (node LockingWaitPolicy) docTable(p *PrettyCfg) []pretty.TableRow {
   879  	str := node.String()
   880  	if str == "" {
   881  		return nil
   882  	}
   883  	return []pretty.TableRow{p.row("", pretty.Keyword(str))}
   884  }
   885  
   886  func (p *PrettyCfg) peelCompOperand(e Expr) Expr {
   887  	if !p.Simplify {
   888  		return e
   889  	}
   890  	stripped := StripParens(e)
   891  	switch stripped.(type) {
   892  	case *FuncExpr, *IndirectionExpr, *UnaryExpr,
   893  		*AnnotateTypeExpr, *CastExpr, *ColumnItem, *UnresolvedName:
   894  		return stripped
   895  	}
   896  	return e
   897  }
   898  
   899  func (node *ComparisonExpr) doc(p *PrettyCfg) pretty.Doc {
   900  	opStr := node.Operator.String()
   901  	// IS and IS NOT are equivalent to IS NOT DISTINCT FROM and IS DISTINCT
   902  	// FROM, respectively, when the RHS is true or false. We prefer the less
   903  	// verbose IS and IS NOT in those cases.
   904  	if node.Operator.Symbol == treecmp.IsDistinctFrom && (node.Right == DBoolTrue || node.Right == DBoolFalse) {
   905  		opStr = "IS NOT"
   906  	} else if node.Operator.Symbol == treecmp.IsNotDistinctFrom && (node.Right == DBoolTrue || node.Right == DBoolFalse) {
   907  		opStr = "IS"
   908  	}
   909  	opDoc := pretty.Keyword(opStr)
   910  	if node.Operator.Symbol.HasSubOperator() {
   911  		opDoc = pretty.ConcatSpace(pretty.Text(node.SubOperator.String()), opDoc)
   912  	}
   913  	return pretty.Group(
   914  		pretty.JoinNestedRight(
   915  			opDoc,
   916  			p.Doc(p.peelCompOperand(node.Left)),
   917  			p.Doc(p.peelCompOperand(node.Right))))
   918  }
   919  
   920  func (node *AliasClause) doc(p *PrettyCfg) pretty.Doc {
   921  	d := pretty.Text(node.Alias.String())
   922  	if len(node.Cols) != 0 {
   923  		d = p.nestUnder(d, p.bracket("(", p.Doc(&node.Cols), ")"))
   924  	}
   925  	return d
   926  }
   927  
   928  func (node *JoinTableExpr) doc(p *PrettyCfg) pretty.Doc {
   929  	//  buf will contain the fully populated sequence of join keywords.
   930  	var buf bytes.Buffer
   931  	cond := pretty.Nil
   932  	if _, isNatural := node.Cond.(NaturalJoinCond); isNatural {
   933  		// Natural joins have a different syntax:
   934  		//   "<a> NATURAL <join_type> [<join_hint>] JOIN <b>"
   935  		buf.WriteString("NATURAL ")
   936  	} else {
   937  		// Regular joins:
   938  		//   "<a> <join type> [<join hint>] JOIN <b>"
   939  		if node.Cond != nil {
   940  			cond = p.Doc(node.Cond)
   941  		}
   942  	}
   943  
   944  	if node.JoinType != "" {
   945  		buf.WriteString(node.JoinType)
   946  		buf.WriteByte(' ')
   947  		if node.Hint != "" {
   948  			buf.WriteString(node.Hint)
   949  			buf.WriteByte(' ')
   950  		}
   951  	}
   952  	buf.WriteString("JOIN")
   953  
   954  	return p.joinNestedOuter(
   955  		buf.String(),
   956  		p.Doc(node.Left),
   957  		pretty.ConcatSpace(p.Doc(node.Right), cond))
   958  }
   959  
   960  func (node *OnJoinCond) doc(p *PrettyCfg) pretty.Doc {
   961  	e := node.Expr
   962  	if p.Simplify {
   963  		e = StripParens(e)
   964  	}
   965  	return p.nestUnder(pretty.Keyword("ON"), p.Doc(e))
   966  }
   967  
   968  func (node *Insert) doc(p *PrettyCfg) pretty.Doc {
   969  	items := make([]pretty.TableRow, 0, 9)
   970  	items = append(items, node.With.docRow(p))
   971  	kw := "INSERT"
   972  	if node.OnConflict.IsUpsertAlias() {
   973  		kw = "UPSERT"
   974  	}
   975  	items = append(items, p.row(kw, pretty.Nil))
   976  
   977  	into := p.Doc(node.Table)
   978  	if node.Columns != nil {
   979  		into = p.nestUnder(into, p.bracket("(", p.Doc(&node.Columns), ")"))
   980  	}
   981  	items = append(items, p.row("INTO", into))
   982  
   983  	if node.DefaultValues() {
   984  		items = append(items, p.row("", pretty.Keyword("DEFAULT VALUES")))
   985  	} else {
   986  		items = append(items, node.Rows.docTable(p)...)
   987  	}
   988  
   989  	if node.OnConflict != nil && !node.OnConflict.IsUpsertAlias() {
   990  		cond := pretty.Nil
   991  		if len(node.OnConflict.Constraint) > 0 {
   992  			cond = p.nestUnder(pretty.Text("ON CONSTRAINT"), p.Doc(&node.OnConflict.Constraint))
   993  		}
   994  		if len(node.OnConflict.Columns) > 0 {
   995  			cond = p.bracket("(", p.Doc(&node.OnConflict.Columns), ")")
   996  		}
   997  		items = append(items, p.row("ON CONFLICT", cond))
   998  		if node.OnConflict.ArbiterPredicate != nil {
   999  			items = append(items, p.row("WHERE", p.Doc(node.OnConflict.ArbiterPredicate)))
  1000  		}
  1001  
  1002  		if node.OnConflict.DoNothing {
  1003  			items = append(items, p.row("DO", pretty.Keyword("NOTHING")))
  1004  		} else {
  1005  			items = append(items, p.row("DO",
  1006  				p.nestUnder(pretty.Keyword("UPDATE SET"), p.Doc(&node.OnConflict.Exprs))))
  1007  			if node.OnConflict.Where != nil {
  1008  				items = append(items, node.OnConflict.Where.docRow(p))
  1009  			}
  1010  		}
  1011  	}
  1012  
  1013  	items = append(items, p.docReturning(node.Returning))
  1014  	return p.rlTable(items...)
  1015  }
  1016  
  1017  func (node *NameList) doc(p *PrettyCfg) pretty.Doc {
  1018  	d := make([]pretty.Doc, len(*node))
  1019  	for i := range *node {
  1020  		d[i] = p.Doc(&(*node)[i])
  1021  	}
  1022  	return p.commaSeparated(d...)
  1023  }
  1024  
  1025  func (node *CastExpr) doc(p *PrettyCfg) pretty.Doc {
  1026  	typ := p.formatType(node.Type)
  1027  
  1028  	switch node.SyntaxMode {
  1029  	case CastPrepend:
  1030  		// This is a special case for things like INTERVAL '1s'. These only work
  1031  		// with string constats; if the underlying expression was changed, we fall
  1032  		// back to the short syntax.
  1033  		if _, ok := node.Expr.(*StrVal); ok {
  1034  			return pretty.Fold(pretty.Concat,
  1035  				typ,
  1036  				pretty.Text(" "),
  1037  				p.Doc(node.Expr),
  1038  			)
  1039  		}
  1040  		fallthrough
  1041  	case CastShort:
  1042  		if typ, ok := GetStaticallyKnownType(node.Type); ok {
  1043  			switch typ.Family() {
  1044  			case types.JsonFamily:
  1045  				if sv, ok := node.Expr.(*StrVal); ok && p.JSONFmt {
  1046  					return p.jsonCast(sv, "::", typ)
  1047  				}
  1048  			}
  1049  		}
  1050  		return pretty.Fold(pretty.Concat,
  1051  			p.exprDocWithParen(node.Expr),
  1052  			pretty.Text("::"),
  1053  			typ,
  1054  		)
  1055  	default:
  1056  		if nTyp, ok := GetStaticallyKnownType(node.Type); ok && nTyp.Family() == types.CollatedStringFamily {
  1057  			// COLLATE clause needs to go after CAST expression, so create
  1058  			// equivalent string type without the locale to get name of string
  1059  			// type without the COLLATE.
  1060  			strTyp := types.MakeScalar(
  1061  				types.StringFamily,
  1062  				nTyp.Oid(),
  1063  				nTyp.Precision(),
  1064  				nTyp.Width(),
  1065  				"", /* locale */
  1066  			)
  1067  			typ = pretty.Text(strTyp.SQLString())
  1068  		}
  1069  
  1070  		ret := pretty.Fold(pretty.Concat,
  1071  			pretty.Keyword("CAST"),
  1072  			p.bracket(
  1073  				"(",
  1074  				p.nestUnder(
  1075  					p.Doc(node.Expr),
  1076  					pretty.Concat(
  1077  						p.keywordWithText("", "AS", " "),
  1078  						typ,
  1079  					),
  1080  				),
  1081  				")",
  1082  			),
  1083  		)
  1084  
  1085  		if nTyp, ok := GetStaticallyKnownType(node.Type); ok && nTyp.Family() == types.CollatedStringFamily {
  1086  			ret = pretty.Fold(pretty.ConcatSpace,
  1087  				ret,
  1088  				pretty.Keyword("COLLATE"),
  1089  				pretty.Text(nTyp.Locale()))
  1090  		}
  1091  		return ret
  1092  	}
  1093  }
  1094  
  1095  func (node *ValuesClause) doc(p *PrettyCfg) pretty.Doc {
  1096  	return p.rlTable(node.docTable(p)...)
  1097  }
  1098  
  1099  func (node *ValuesClause) docTable(p *PrettyCfg) []pretty.TableRow {
  1100  	d := make([]pretty.Doc, len(node.Rows))
  1101  	for i := range node.Rows {
  1102  		d[i] = p.bracket("(", p.Doc(&node.Rows[i]), ")")
  1103  	}
  1104  	return []pretty.TableRow{p.row("VALUES", p.commaSeparated(d...))}
  1105  }
  1106  
  1107  func (node *StatementSource) doc(p *PrettyCfg) pretty.Doc {
  1108  	return p.bracket("[", p.Doc(node.Statement), "]")
  1109  }
  1110  
  1111  func (node *RowsFromExpr) doc(p *PrettyCfg) pretty.Doc {
  1112  	if p.Simplify && len(node.Items) == 1 {
  1113  		return p.Doc(node.Items[0])
  1114  	}
  1115  	return p.bracketKeyword("ROWS FROM", " (", p.Doc(&node.Items), ")", "")
  1116  }
  1117  
  1118  func (node *Array) doc(p *PrettyCfg) pretty.Doc {
  1119  	return p.bracketKeyword("ARRAY", "[", p.Doc(&node.Exprs), "]", "")
  1120  }
  1121  
  1122  func (node *Tuple) doc(p *PrettyCfg) pretty.Doc {
  1123  	exprDoc := p.Doc(&node.Exprs)
  1124  	if len(node.Exprs) == 1 {
  1125  		exprDoc = pretty.Concat(exprDoc, pretty.Text(","))
  1126  	}
  1127  	d := p.bracket("(", exprDoc, ")")
  1128  	if len(node.Labels) > 0 {
  1129  		labels := make([]pretty.Doc, len(node.Labels))
  1130  		for i := range node.Labels {
  1131  			n := &node.Labels[i]
  1132  			labels[i] = p.Doc((*Name)(n))
  1133  		}
  1134  		d = p.bracket("(", pretty.Stack(
  1135  			d,
  1136  			p.nestUnder(pretty.Keyword("AS"), p.commaSeparated(labels...)),
  1137  		), ")")
  1138  	}
  1139  	return d
  1140  }
  1141  
  1142  func (node *UpdateExprs) doc(p *PrettyCfg) pretty.Doc {
  1143  	d := make([]pretty.Doc, len(*node))
  1144  	for i, n := range *node {
  1145  		d[i] = p.Doc(n)
  1146  	}
  1147  	return p.commaSeparated(d...)
  1148  }
  1149  
  1150  func (p *PrettyCfg) exprDocWithParen(e Expr) pretty.Doc {
  1151  	if _, ok := e.(operatorExpr); ok {
  1152  		return p.bracket("(", p.Doc(e), ")")
  1153  	}
  1154  	return p.Doc(e)
  1155  }
  1156  
  1157  func (node *Update) doc(p *PrettyCfg) pretty.Doc {
  1158  	items := make([]pretty.TableRow, 0, 8)
  1159  	items = append(items,
  1160  		node.With.docRow(p),
  1161  		p.row("UPDATE", p.Doc(node.Table)),
  1162  		p.row("SET", p.Doc(&node.Exprs)))
  1163  	if len(node.From) > 0 {
  1164  		items = append(items,
  1165  			p.row("FROM", p.Doc(&node.From)))
  1166  	}
  1167  	items = append(items,
  1168  		node.Where.docRow(p),
  1169  		node.OrderBy.docRow(p))
  1170  	items = append(items, node.Limit.docTable(p)...)
  1171  	items = append(items, p.docReturning(node.Returning))
  1172  	return p.rlTable(items...)
  1173  }
  1174  
  1175  func (node *Delete) doc(p *PrettyCfg) pretty.Doc {
  1176  	items := make([]pretty.TableRow, 0, 7)
  1177  	items = append(items,
  1178  		node.With.docRow(p))
  1179  	tableLbl := "DELETE FROM"
  1180  	batch := node.Batch
  1181  	if batch != nil {
  1182  		tableLbl = "FROM"
  1183  		items = append(items,
  1184  			p.row("DELETE", p.Doc(batch)))
  1185  	}
  1186  	items = append(items,
  1187  		p.row(tableLbl, p.Doc(node.Table)))
  1188  	if len(node.Using) > 0 {
  1189  		items = append(items, p.row("USING", p.Doc(&node.Using)))
  1190  	}
  1191  	items = append(items,
  1192  		node.Where.docRow(p),
  1193  		node.OrderBy.docRow(p))
  1194  	items = append(items, node.Limit.docTable(p)...)
  1195  	items = append(items, p.docReturning(node.Returning))
  1196  	return p.rlTable(items...)
  1197  }
  1198  
  1199  func (p *PrettyCfg) docReturning(node ReturningClause) pretty.TableRow {
  1200  	switch r := node.(type) {
  1201  	case *NoReturningClause:
  1202  		return p.row("", nil)
  1203  	case *ReturningNothing:
  1204  		return p.row("RETURNING", pretty.Keyword("NOTHING"))
  1205  	case *ReturningExprs:
  1206  		return p.row("RETURNING", p.Doc((*SelectExprs)(r)))
  1207  	default:
  1208  		panic(errors.AssertionFailedf("unhandled case: %T", node))
  1209  	}
  1210  }
  1211  
  1212  func (node *Order) doc(p *PrettyCfg) pretty.Doc {
  1213  	var d pretty.Doc
  1214  	if node.OrderType == OrderByColumn {
  1215  		d = p.Doc(node.Expr)
  1216  	} else {
  1217  		if node.Index == "" {
  1218  			d = pretty.ConcatSpace(
  1219  				pretty.Keyword("PRIMARY KEY"),
  1220  				p.Doc(&node.Table),
  1221  			)
  1222  		} else {
  1223  			d = pretty.ConcatSpace(
  1224  				pretty.Keyword("INDEX"),
  1225  				pretty.Fold(pretty.Concat,
  1226  					p.Doc(&node.Table),
  1227  					pretty.Text("@"),
  1228  					p.Doc(&node.Index),
  1229  				),
  1230  			)
  1231  		}
  1232  	}
  1233  	if node.Direction != DefaultDirection {
  1234  		d = p.nestUnder(d, pretty.Text(node.Direction.String()))
  1235  	}
  1236  	if node.NullsOrder != DefaultNullsOrder {
  1237  		d = p.nestUnder(d, pretty.Text(node.NullsOrder.String()))
  1238  	}
  1239  	return d
  1240  }
  1241  
  1242  func (node *UpdateExpr) doc(p *PrettyCfg) pretty.Doc {
  1243  	d := p.Doc(&node.Names)
  1244  	if node.Tuple {
  1245  		d = p.bracket("(", d, ")")
  1246  	}
  1247  	e := node.Expr
  1248  	if p.Simplify {
  1249  		e = StripParens(e)
  1250  	}
  1251  	return p.nestUnder(d, pretty.ConcatSpace(pretty.Text("="), p.Doc(e)))
  1252  }
  1253  
  1254  func (node *CreateTable) doc(p *PrettyCfg) pretty.Doc {
  1255  	// Final layout:
  1256  	//
  1257  	// CREATE [TEMP | UNLOGGED] TABLE [IF NOT EXISTS] name ( .... ) [AS]
  1258  	//     [SELECT ...] - for CREATE TABLE AS
  1259  	//     [INTERLEAVE ...]
  1260  	//     [PARTITION BY ...]
  1261  	//
  1262  	title := pretty.Keyword("CREATE")
  1263  	switch node.Persistence {
  1264  	case PersistenceTemporary:
  1265  		title = pretty.ConcatSpace(title, pretty.Keyword("TEMPORARY"))
  1266  	case PersistenceUnlogged:
  1267  		title = pretty.ConcatSpace(title, pretty.Keyword("UNLOGGED"))
  1268  	}
  1269  	title = pretty.ConcatSpace(title, pretty.Keyword("TABLE"))
  1270  	if node.IfNotExists {
  1271  		title = pretty.ConcatSpace(title, pretty.Keyword("IF NOT EXISTS"))
  1272  	}
  1273  	title = pretty.ConcatSpace(title, p.Doc(&node.Table))
  1274  
  1275  	if node.As() {
  1276  		if len(node.Defs) > 0 {
  1277  			title = pretty.ConcatSpace(title,
  1278  				p.bracket("(", p.Doc(&node.Defs), ")"))
  1279  		}
  1280  		if node.StorageParams != nil {
  1281  			title = pretty.ConcatSpace(title, pretty.Keyword("WITH"))
  1282  			title = pretty.ConcatSpace(title, p.bracket(`(`, p.Doc(&node.StorageParams), `)`))
  1283  		}
  1284  		title = pretty.ConcatSpace(title, pretty.Keyword("AS"))
  1285  	} else {
  1286  		title = pretty.ConcatSpace(title,
  1287  			p.bracket("(", p.Doc(&node.Defs), ")"),
  1288  		)
  1289  	}
  1290  
  1291  	clauses := make([]pretty.Doc, 0, 4)
  1292  	if node.As() {
  1293  		clauses = append(clauses, p.Doc(node.AsSource))
  1294  	}
  1295  	if node.PartitionByTable != nil {
  1296  		clauses = append(clauses, p.Doc(node.PartitionByTable))
  1297  	}
  1298  	if node.StorageParams != nil && !node.As() {
  1299  		clauses = append(
  1300  			clauses,
  1301  			pretty.ConcatSpace(
  1302  				pretty.Keyword(`WITH`),
  1303  				p.bracket(`(`, p.Doc(&node.StorageParams), `)`),
  1304  			),
  1305  		)
  1306  	}
  1307  	if node.Locality != nil {
  1308  		clauses = append(clauses, p.Doc(node.Locality))
  1309  	}
  1310  	if len(clauses) == 0 {
  1311  		return title
  1312  	}
  1313  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1314  }
  1315  
  1316  func (node *CreateView) doc(p *PrettyCfg) pretty.Doc {
  1317  	// Final layout:
  1318  	//
  1319  	// CREATE [TEMP] VIEW name ( ... ) AS
  1320  	//     SELECT ...
  1321  	//
  1322  	title := pretty.Keyword("CREATE")
  1323  	if node.Replace {
  1324  		title = pretty.ConcatSpace(title, pretty.Keyword("OR REPLACE"))
  1325  	}
  1326  	if node.Persistence == PersistenceTemporary {
  1327  		title = pretty.ConcatSpace(title, pretty.Keyword("TEMPORARY"))
  1328  	}
  1329  	if node.Materialized {
  1330  		title = pretty.ConcatSpace(title, pretty.Keyword("MATERIALIZED"))
  1331  	}
  1332  	title = pretty.ConcatSpace(title, pretty.Keyword("VIEW"))
  1333  	if node.IfNotExists {
  1334  		title = pretty.ConcatSpace(title, pretty.Keyword("IF NOT EXISTS"))
  1335  	}
  1336  	d := pretty.ConcatSpace(
  1337  		title,
  1338  		p.Doc(&node.Name),
  1339  	)
  1340  	if len(node.ColumnNames) > 0 {
  1341  		d = pretty.ConcatSpace(
  1342  			d,
  1343  			p.bracket("(", p.Doc(&node.ColumnNames), ")"),
  1344  		)
  1345  	}
  1346  	d = p.nestUnder(
  1347  		pretty.ConcatSpace(d, pretty.Keyword("AS")),
  1348  		p.Doc(node.AsSource),
  1349  	)
  1350  	if node.Materialized && node.WithData {
  1351  		d = pretty.ConcatSpace(d, pretty.Keyword("WITH DATA"))
  1352  	} else if node.Materialized && !node.WithData {
  1353  		d = pretty.ConcatSpace(d, pretty.Keyword("WITH NO DATA"))
  1354  	}
  1355  	return d
  1356  }
  1357  
  1358  func (node *TableDefs) doc(p *PrettyCfg) pretty.Doc {
  1359  	// This groups column definitions using a table to get alignment of
  1360  	// column names, and separately comma-joins groups of column definitions
  1361  	// with constraint definitions.
  1362  
  1363  	defs := *node
  1364  	colDefRows := make([]pretty.TableRow, 0, len(defs))
  1365  	items := make([]pretty.Doc, 0, len(defs))
  1366  
  1367  	for i := 0; i < len(defs); i++ {
  1368  		if _, ok := defs[i].(*ColumnTableDef); ok {
  1369  			// Group all the subsequent column definitions into a table.
  1370  			j := i
  1371  			colDefRows = colDefRows[:0]
  1372  			for ; j < len(defs); j++ {
  1373  				cdef, ok := defs[j].(*ColumnTableDef)
  1374  				if !ok {
  1375  					break
  1376  				}
  1377  				colDefRows = append(colDefRows, cdef.docRow(p))
  1378  			}
  1379  			// Let the outer loop pick up where we left.
  1380  			i = j - 1
  1381  
  1382  			// At this point the column definitions form a table, but the comma
  1383  			// is missing from each row. We need to add it here. However we
  1384  			// need to be careful. Since we're going to add a comma between the
  1385  			// set of all column definitions and the other table definitions
  1386  			// below (via commaSeparated), we need to ensure the last row does
  1387  			// not get a comma.
  1388  			for j = 0; j < len(colDefRows)-1; j++ {
  1389  				colDefRows[j].Doc = pretty.Concat(colDefRows[j].Doc, pretty.Text(","))
  1390  			}
  1391  			items = append(items, p.llTable(pretty.Text, colDefRows...))
  1392  		} else {
  1393  			// Not a column definition, just process normally.
  1394  			items = append(items, p.Doc(defs[i]))
  1395  		}
  1396  	}
  1397  
  1398  	return p.commaSeparated(items...)
  1399  }
  1400  
  1401  func (node *CaseExpr) doc(p *PrettyCfg) pretty.Doc {
  1402  	d := make([]pretty.Doc, 0, len(node.Whens)+3)
  1403  	c := pretty.Keyword("CASE")
  1404  	if node.Expr != nil {
  1405  		c = pretty.Group(pretty.ConcatSpace(c, p.Doc(node.Expr)))
  1406  	}
  1407  	d = append(d, c)
  1408  	for _, when := range node.Whens {
  1409  		d = append(d, p.Doc(when))
  1410  	}
  1411  	if node.Else != nil {
  1412  		d = append(d, pretty.Group(pretty.ConcatSpace(
  1413  			pretty.Keyword("ELSE"),
  1414  			p.Doc(node.Else),
  1415  		)))
  1416  	}
  1417  	d = append(d, pretty.Keyword("END"))
  1418  	return pretty.Stack(d...)
  1419  }
  1420  
  1421  func (node *When) doc(p *PrettyCfg) pretty.Doc {
  1422  	return pretty.Group(pretty.ConcatLine(
  1423  		pretty.Group(pretty.ConcatSpace(
  1424  			pretty.Keyword("WHEN"),
  1425  			p.Doc(node.Cond),
  1426  		)),
  1427  		pretty.Group(pretty.ConcatSpace(
  1428  			pretty.Keyword("THEN"),
  1429  			p.Doc(node.Val),
  1430  		)),
  1431  	))
  1432  }
  1433  
  1434  func (node *UnionClause) doc(p *PrettyCfg) pretty.Doc {
  1435  	op := node.Type.String()
  1436  	if node.All {
  1437  		op += " ALL"
  1438  	}
  1439  	return pretty.Stack(p.Doc(node.Left), p.nestUnder(pretty.Keyword(op), p.Doc(node.Right)))
  1440  }
  1441  
  1442  func (node *IfErrExpr) doc(p *PrettyCfg) pretty.Doc {
  1443  	var s string
  1444  	if node.Else != nil {
  1445  		s = "IFERROR"
  1446  	} else {
  1447  		s = "ISERROR"
  1448  	}
  1449  	d := []pretty.Doc{p.Doc(node.Cond)}
  1450  	if node.Else != nil {
  1451  		d = append(d, p.Doc(node.Else))
  1452  	}
  1453  	if node.ErrCode != nil {
  1454  		d = append(d, p.Doc(node.ErrCode))
  1455  	}
  1456  	return p.bracketKeyword(s, "(", p.commaSeparated(d...), ")", "")
  1457  }
  1458  
  1459  func (node *IfExpr) doc(p *PrettyCfg) pretty.Doc {
  1460  	return p.bracketKeyword("IF", "(",
  1461  		p.commaSeparated(
  1462  			p.Doc(node.Cond),
  1463  			p.Doc(node.True),
  1464  			p.Doc(node.Else),
  1465  		), ")", "")
  1466  }
  1467  
  1468  func (node *NullIfExpr) doc(p *PrettyCfg) pretty.Doc {
  1469  	return p.bracketKeyword("NULLIF", "(",
  1470  		p.commaSeparated(
  1471  			p.Doc(node.Expr1),
  1472  			p.Doc(node.Expr2),
  1473  		), ")", "")
  1474  }
  1475  
  1476  func (node *PartitionByTable) doc(p *PrettyCfg) pretty.Doc {
  1477  	// Final layout:
  1478  	//
  1479  	// PARTITION [ALL] BY NOTHING
  1480  	//
  1481  	// PARTITION [ALL] BY LIST (...)
  1482  	//    ( ..values.. )
  1483  	//
  1484  	// PARTITION [ALL] BY RANGE (...)
  1485  	//    ( ..values.. )
  1486  	var kw string
  1487  	kw = `PARTITION `
  1488  	if node.All {
  1489  		kw += `ALL `
  1490  	}
  1491  	return node.PartitionBy.docInner(p, kw+`BY `)
  1492  }
  1493  
  1494  func (node *PartitionBy) doc(p *PrettyCfg) pretty.Doc {
  1495  	// Final layout:
  1496  	//
  1497  	// PARTITION BY NOTHING
  1498  	//
  1499  	// PARTITION BY LIST (...)
  1500  	//    ( ..values.. )
  1501  	//
  1502  	// PARTITION BY RANGE (...)
  1503  	//    ( ..values.. )
  1504  	return node.docInner(p, `PARTITION BY `)
  1505  }
  1506  
  1507  func (node *PartitionBy) docInner(p *PrettyCfg, kw string) pretty.Doc {
  1508  	if node == nil {
  1509  		return pretty.Keyword(kw + `NOTHING`)
  1510  	}
  1511  	if len(node.List) > 0 {
  1512  		kw += `LIST`
  1513  	} else if len(node.Range) > 0 {
  1514  		kw += `RANGE`
  1515  	}
  1516  	title := pretty.ConcatSpace(pretty.Keyword(kw),
  1517  		p.bracket("(", p.Doc(&node.Fields), ")"))
  1518  
  1519  	inner := make([]pretty.Doc, 0, len(node.List)+len(node.Range))
  1520  	for _, v := range node.List {
  1521  		inner = append(inner, p.Doc(&v))
  1522  	}
  1523  	for _, v := range node.Range {
  1524  		inner = append(inner, p.Doc(&v))
  1525  	}
  1526  	return p.nestUnder(title,
  1527  		p.bracket("(", p.commaSeparated(inner...), ")"),
  1528  	)
  1529  }
  1530  
  1531  func (node *Locality) doc(p *PrettyCfg) pretty.Doc {
  1532  	// Final layout:
  1533  	//
  1534  	// LOCALITY [GLOBAL | REGIONAL BY [TABLE [IN [PRIMARY REGION|region]]|ROW]]
  1535  	localityKW := pretty.Keyword("LOCALITY")
  1536  	switch node.LocalityLevel {
  1537  	case LocalityLevelGlobal:
  1538  		return pretty.ConcatSpace(localityKW, pretty.Keyword("GLOBAL"))
  1539  	case LocalityLevelRow:
  1540  		ret := pretty.ConcatSpace(localityKW, pretty.Keyword("REGIONAL BY ROW"))
  1541  		if node.RegionalByRowColumn != "" {
  1542  			return pretty.ConcatSpace(
  1543  				ret,
  1544  				pretty.ConcatSpace(
  1545  					pretty.Keyword("AS"),
  1546  					p.Doc(&node.RegionalByRowColumn),
  1547  				),
  1548  			)
  1549  		}
  1550  		return ret
  1551  	case LocalityLevelTable:
  1552  		byTable := pretty.ConcatSpace(localityKW, pretty.Keyword("REGIONAL BY TABLE IN"))
  1553  		if node.TableRegion == "" {
  1554  			return pretty.ConcatSpace(
  1555  				byTable,
  1556  				pretty.Keyword("PRIMARY REGION"),
  1557  			)
  1558  		}
  1559  		return pretty.ConcatSpace(
  1560  			byTable,
  1561  			p.Doc(&node.TableRegion),
  1562  		)
  1563  	}
  1564  	panic(fmt.Sprintf("unknown locality: %v", *node))
  1565  }
  1566  
  1567  func (node *ListPartition) doc(p *PrettyCfg) pretty.Doc {
  1568  	// Final layout:
  1569  	//
  1570  	// PARTITION name
  1571  	//   VALUES IN ( ... )
  1572  	//   [ .. subpartition ..]
  1573  	//
  1574  	title := pretty.ConcatSpace(pretty.Keyword("PARTITION"), p.Doc(&node.Name))
  1575  
  1576  	clauses := make([]pretty.Doc, 1, 2)
  1577  	clauses[0] = pretty.ConcatSpace(
  1578  		pretty.Keyword("VALUES IN"),
  1579  		p.bracket("(", p.Doc(&node.Exprs), ")"),
  1580  	)
  1581  	if node.Subpartition != nil {
  1582  		clauses = append(clauses, p.Doc(node.Subpartition))
  1583  	}
  1584  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1585  }
  1586  
  1587  func (node *RangePartition) doc(p *PrettyCfg) pretty.Doc {
  1588  	// Final layout:
  1589  	//
  1590  	// PARTITION name
  1591  	//   VALUES FROM (...)
  1592  	//   TO (...)
  1593  	//   [ .. subpartition ..]
  1594  	//
  1595  	title := pretty.ConcatSpace(
  1596  		pretty.Keyword("PARTITION"),
  1597  		p.Doc(&node.Name),
  1598  	)
  1599  
  1600  	clauses := make([]pretty.Doc, 2, 3)
  1601  	clauses[0] = pretty.ConcatSpace(
  1602  		pretty.Keyword("VALUES FROM"),
  1603  		p.bracket("(", p.Doc(&node.From), ")"))
  1604  	clauses[1] = pretty.ConcatSpace(
  1605  		pretty.Keyword("TO"),
  1606  		p.bracket("(", p.Doc(&node.To), ")"))
  1607  
  1608  	if node.Subpartition != nil {
  1609  		clauses = append(clauses, p.Doc(node.Subpartition))
  1610  	}
  1611  
  1612  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1613  }
  1614  
  1615  func (node *ShardedIndexDef) doc(p *PrettyCfg) pretty.Doc {
  1616  	// Final layout:
  1617  	//
  1618  	// USING HASH [WITH BUCKET_COUNT = bucket_count]
  1619  	//
  1620  	if _, ok := node.ShardBuckets.(DefaultVal); ok {
  1621  		return pretty.Keyword("USING HASH")
  1622  	}
  1623  	parts := []pretty.Doc{
  1624  		pretty.Keyword("USING HASH WITH BUCKET_COUNT = "),
  1625  		p.Doc(node.ShardBuckets),
  1626  	}
  1627  	return pretty.Fold(pretty.ConcatSpace, parts...)
  1628  }
  1629  
  1630  func (node *CreateIndex) doc(p *PrettyCfg) pretty.Doc {
  1631  	// Final layout:
  1632  	// CREATE [UNIQUE] [INVERTED] INDEX [name]
  1633  	//    ON tbl (cols...)
  1634  	//    [STORING ( ... )]
  1635  	//    [INTERLEAVE ...]
  1636  	//    [PARTITION BY ...]
  1637  	//    [WITH ...]
  1638  	//    [WHERE ...]
  1639  	//    [NOT VISIBLE | VISIBILITY ...]
  1640  	//
  1641  	title := make([]pretty.Doc, 0, 7)
  1642  	title = append(title, pretty.Keyword("CREATE"))
  1643  	if node.Unique {
  1644  		title = append(title, pretty.Keyword("UNIQUE"))
  1645  	}
  1646  	if node.Inverted {
  1647  		title = append(title, pretty.Keyword("INVERTED"))
  1648  	}
  1649  	title = append(title, pretty.Keyword("INDEX"))
  1650  	if node.Concurrently {
  1651  		title = append(title, pretty.Keyword("CONCURRENTLY"))
  1652  	}
  1653  	if node.IfNotExists {
  1654  		title = append(title, pretty.Keyword("IF NOT EXISTS"))
  1655  	}
  1656  	if node.Name != "" {
  1657  		title = append(title, p.Doc(&node.Name))
  1658  	}
  1659  
  1660  	clauses := make([]pretty.Doc, 0, 7)
  1661  	clauses = append(clauses, pretty.Fold(pretty.ConcatSpace,
  1662  		pretty.Keyword("ON"),
  1663  		p.Doc(&node.Table),
  1664  		p.bracket("(", p.Doc(&node.Columns), ")")))
  1665  
  1666  	if node.Sharded != nil {
  1667  		clauses = append(clauses, p.Doc(node.Sharded))
  1668  	}
  1669  	if len(node.Storing) > 0 {
  1670  		clauses = append(clauses, p.bracketKeyword(
  1671  			"STORING", " (",
  1672  			p.Doc(&node.Storing),
  1673  			")", "",
  1674  		))
  1675  	}
  1676  	if node.PartitionByIndex != nil {
  1677  		clauses = append(clauses, p.Doc(node.PartitionByIndex))
  1678  	}
  1679  	if node.StorageParams != nil {
  1680  		clauses = append(clauses, p.bracketKeyword(
  1681  			"WITH", " (",
  1682  			p.Doc(&node.StorageParams),
  1683  			")", "",
  1684  		))
  1685  	}
  1686  	if node.Predicate != nil {
  1687  		clauses = append(clauses, p.nestUnder(pretty.Keyword("WHERE"), p.Doc(node.Predicate)))
  1688  	}
  1689  	switch {
  1690  	case node.Invisibility.FloatProvided:
  1691  		clauses = append(clauses,
  1692  			pretty.Keyword(" VISIBILITY "+fmt.Sprintf("%.2f", 1-node.Invisibility.Value)))
  1693  	case node.Invisibility.Value == 1.0:
  1694  		clauses = append(clauses, pretty.Keyword(" NOT VISIBLE"))
  1695  	}
  1696  	return p.nestUnder(
  1697  		pretty.Fold(pretty.ConcatSpace, title...),
  1698  		pretty.Group(pretty.Stack(clauses...)))
  1699  }
  1700  
  1701  func (node *FamilyTableDef) doc(p *PrettyCfg) pretty.Doc {
  1702  	// Final layout:
  1703  	// FAMILY [name] (columns...)
  1704  	//
  1705  	d := pretty.Keyword("FAMILY")
  1706  	if node.Name != "" {
  1707  		d = pretty.ConcatSpace(d, p.Doc(&node.Name))
  1708  	}
  1709  	return pretty.ConcatSpace(d, p.bracket("(", p.Doc(&node.Columns), ")"))
  1710  }
  1711  
  1712  func (node *LikeTableDef) doc(p *PrettyCfg) pretty.Doc {
  1713  	d := pretty.Keyword("LIKE")
  1714  	d = pretty.ConcatSpace(d, p.Doc(&node.Name))
  1715  	for _, opt := range node.Options {
  1716  		word := "INCLUDING"
  1717  		if opt.Excluded {
  1718  			word = "EXCLUDING"
  1719  		}
  1720  		d = pretty.ConcatSpace(d, pretty.Keyword(word))
  1721  		d = pretty.ConcatSpace(d, pretty.Keyword(opt.Opt.String()))
  1722  	}
  1723  	return d
  1724  }
  1725  
  1726  func (node *IndexTableDef) doc(p *PrettyCfg) pretty.Doc {
  1727  	// Final layout:
  1728  	// [INVERTED] INDEX [name] (columns...)
  1729  	//    [STORING ( ... )]
  1730  	//    [INTERLEAVE ...]
  1731  	//    [PARTITION BY ...]
  1732  	//    [WHERE ...]
  1733  	//    [NOT VISIBLE | VISIBILITY ...]
  1734  	//
  1735  	title := pretty.Keyword("INDEX")
  1736  	if node.Name != "" {
  1737  		title = pretty.ConcatSpace(title, p.Doc(&node.Name))
  1738  	}
  1739  	if node.Inverted {
  1740  		title = pretty.ConcatSpace(pretty.Keyword("INVERTED"), title)
  1741  	}
  1742  	title = pretty.ConcatSpace(title, p.bracket("(", p.Doc(&node.Columns), ")"))
  1743  
  1744  	clauses := make([]pretty.Doc, 0, 6)
  1745  	if node.Sharded != nil {
  1746  		clauses = append(clauses, p.Doc(node.Sharded))
  1747  	}
  1748  	if node.Storing != nil {
  1749  		clauses = append(clauses, p.bracketKeyword(
  1750  			"STORING", "(",
  1751  			p.Doc(&node.Storing),
  1752  			")", ""))
  1753  	}
  1754  	if node.PartitionByIndex != nil {
  1755  		clauses = append(clauses, p.Doc(node.PartitionByIndex))
  1756  	}
  1757  	if node.StorageParams != nil {
  1758  		clauses = append(
  1759  			clauses,
  1760  			p.bracketKeyword("WITH", "(", p.Doc(&node.StorageParams), ")", ""),
  1761  		)
  1762  	}
  1763  	if node.Predicate != nil {
  1764  		clauses = append(clauses, p.nestUnder(pretty.Keyword("WHERE"), p.Doc(node.Predicate)))
  1765  	}
  1766  	switch {
  1767  	case node.Invisibility.FloatProvided:
  1768  		clauses = append(clauses,
  1769  			pretty.Keyword(" VISIBILITY "+fmt.Sprintf("%.2f", 1-node.Invisibility.Value)))
  1770  	case node.Invisibility.Value == 1.0:
  1771  		clauses = append(clauses, pretty.Keyword(" NOT VISIBLE"))
  1772  	}
  1773  	if len(clauses) == 0 {
  1774  		return title
  1775  	}
  1776  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1777  }
  1778  
  1779  func (node *UniqueConstraintTableDef) doc(p *PrettyCfg) pretty.Doc {
  1780  	// Final layout:
  1781  	// [CONSTRAINT name]
  1782  	//    [PRIMARY KEY|UNIQUE [WITHOUT INDEX]] ( ... )
  1783  	//    [STORING ( ... )]
  1784  	//    [INTERLEAVE ...]
  1785  	//    [PARTITION BY ...]
  1786  	//    [WHERE ...]
  1787  	//    [NOT VISIBLE | VISIBILITY ...]
  1788  	//
  1789  	// or (no constraint name):
  1790  	//
  1791  	// [PRIMARY KEY|UNIQUE [WITHOUT INDEX]] ( ... )
  1792  	//    [STORING ( ... )]
  1793  	//    [INTERLEAVE ...]
  1794  	//    [PARTITION BY ...]
  1795  	//    [WHERE ...]
  1796  	//    [NOT VISIBLE | VISIBILITY ...]
  1797  	//
  1798  	clauses := make([]pretty.Doc, 0, 6)
  1799  	var title pretty.Doc
  1800  	if node.PrimaryKey {
  1801  		title = pretty.Keyword("PRIMARY KEY")
  1802  	} else {
  1803  		title = pretty.Keyword("UNIQUE")
  1804  		if node.WithoutIndex {
  1805  			title = pretty.ConcatSpace(title, pretty.Keyword("WITHOUT INDEX"))
  1806  		}
  1807  	}
  1808  	title = pretty.ConcatSpace(title, p.bracket("(", p.Doc(&node.Columns), ")"))
  1809  	if node.Name != "" {
  1810  		clauses = append(clauses, title)
  1811  		title = pretty.ConcatSpace(pretty.Keyword("CONSTRAINT"), p.Doc(&node.Name))
  1812  	}
  1813  	if node.Sharded != nil {
  1814  		clauses = append(clauses, p.Doc(node.Sharded))
  1815  	}
  1816  	if node.Storing != nil {
  1817  		clauses = append(clauses, p.bracketKeyword(
  1818  			"STORING", "(",
  1819  			p.Doc(&node.Storing),
  1820  			")", ""))
  1821  	}
  1822  
  1823  	if node.PartitionByIndex != nil {
  1824  		clauses = append(clauses, p.Doc(node.PartitionByIndex))
  1825  	}
  1826  	if node.Predicate != nil {
  1827  		clauses = append(clauses, p.nestUnder(pretty.Keyword("WHERE"), p.Doc(node.Predicate)))
  1828  	}
  1829  	switch {
  1830  	case node.Invisibility.FloatProvided:
  1831  		clauses = append(clauses,
  1832  			pretty.Keyword(" VISIBILITY "+fmt.Sprintf("%.2f", 1-node.Invisibility.Value)))
  1833  	case node.Invisibility.Value == 1.0:
  1834  		clauses = append(clauses, pretty.Keyword(" NOT VISIBLE"))
  1835  	}
  1836  	if node.StorageParams != nil {
  1837  		clauses = append(clauses, p.bracketKeyword(
  1838  			"WITH", "(",
  1839  			p.Doc(&node.StorageParams),
  1840  			")", ""))
  1841  	}
  1842  
  1843  	if len(clauses) == 0 {
  1844  		return title
  1845  	}
  1846  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1847  }
  1848  
  1849  func (node *ForeignKeyConstraintTableDef) doc(p *PrettyCfg) pretty.Doc {
  1850  	// Final layout:
  1851  	// [CONSTRAINT name]
  1852  	//    FOREIGN KEY (...)
  1853  	//    REFERENCES tbl (...)
  1854  	//    [MATCH ...]
  1855  	//    [ACTIONS ...]
  1856  	//
  1857  	// or (no constraint name):
  1858  	//
  1859  	// FOREIGN KEY (...)
  1860  	//    REFERENCES tbl [(...)]
  1861  	//    [MATCH ...]
  1862  	//    [ACTIONS ...]
  1863  	//
  1864  	clauses := make([]pretty.Doc, 0, 4)
  1865  	title := pretty.ConcatSpace(
  1866  		pretty.Keyword("FOREIGN KEY"),
  1867  		p.bracket("(", p.Doc(&node.FromCols), ")"))
  1868  
  1869  	if node.Name != "" {
  1870  		clauses = append(clauses, title)
  1871  		title = pretty.ConcatSpace(pretty.Keyword("CONSTRAINT"), p.Doc(&node.Name))
  1872  	}
  1873  
  1874  	ref := pretty.ConcatSpace(
  1875  		pretty.Keyword("REFERENCES"), p.Doc(&node.Table))
  1876  	if len(node.ToCols) > 0 {
  1877  		ref = pretty.ConcatSpace(ref, p.bracket("(", p.Doc(&node.ToCols), ")"))
  1878  	}
  1879  	clauses = append(clauses, ref)
  1880  
  1881  	if node.Match != MatchSimple {
  1882  		clauses = append(clauses, pretty.Keyword(node.Match.String()))
  1883  	}
  1884  
  1885  	if actions := p.Doc(&node.Actions); ref != pretty.Nil {
  1886  		clauses = append(clauses, actions)
  1887  	}
  1888  
  1889  	return p.nestUnder(title, pretty.Group(pretty.Stack(clauses...)))
  1890  }
  1891  
  1892  func (p *PrettyCfg) maybePrependConstraintName(constraintName *Name, d pretty.Doc) pretty.Doc {
  1893  	if *constraintName != "" {
  1894  		return pretty.Fold(pretty.ConcatSpace,
  1895  			pretty.Keyword("CONSTRAINT"),
  1896  			p.Doc(constraintName),
  1897  			d)
  1898  	}
  1899  	return d
  1900  }
  1901  
  1902  func (node *ColumnTableDef) doc(p *PrettyCfg) pretty.Doc {
  1903  	return p.unrow(node.docRow(p))
  1904  }
  1905  
  1906  func (node *ColumnTableDef) docRow(p *PrettyCfg) pretty.TableRow {
  1907  	// Final layout:
  1908  	// colname
  1909  	//   type
  1910  	//   [AS ( ... ) STORED]
  1911  	//   [GENERATED {ALWAYS|BY DEFAULT} AS IDENTITY]
  1912  	//   [[CREATE [IF NOT EXISTS]] FAMILY [name]]
  1913  	//   [[CONSTRAINT name] DEFAULT expr]
  1914  	//   [[CONSTRAINT name] {NULL|NOT NULL}]
  1915  	//   [[CONSTRAINT name] {PRIMARY KEY|UNIQUE [WITHOUT INDEX]}]
  1916  	//   [[CONSTRAINT name] CHECK ...]
  1917  	//   [[CONSTRAINT name] REFERENCES tbl (...)
  1918  	//         [MATCH ...]
  1919  	//         [ACTIONS ...]
  1920  	//   ]
  1921  	//
  1922  	clauses := make([]pretty.Doc, 0, 14)
  1923  
  1924  	// Column type.
  1925  	// ColumnTableDef node type will not be specified if it represents a CREATE
  1926  	// TABLE ... AS query.
  1927  	if node.Type != nil {
  1928  		clauses = append(clauses, func() pretty.Doc {
  1929  			if name, replaced := node.replacedSerialTypeName(); replaced {
  1930  				return pretty.Text(name)
  1931  			}
  1932  			return p.formatType(node.Type)
  1933  		}())
  1934  	}
  1935  
  1936  	// Compute expression (for computed columns).
  1937  	if node.IsComputed() {
  1938  		var typ string
  1939  		if node.Computed.Virtual {
  1940  			typ = "VIRTUAL"
  1941  		} else {
  1942  			typ = "STORED"
  1943  		}
  1944  
  1945  		clauses = append(clauses, pretty.ConcatSpace(
  1946  			pretty.Keyword("AS"),
  1947  			pretty.ConcatSpace(
  1948  				p.bracket("(", p.Doc(node.Computed.Expr), ")"),
  1949  				pretty.Keyword(typ),
  1950  			),
  1951  		))
  1952  	}
  1953  
  1954  	// GENERATED ALWAYS/BY DEFAULT AS IDENTITY constraint.
  1955  	if node.GeneratedIdentity.IsGeneratedAsIdentity {
  1956  		var generatedConstraint pretty.Doc
  1957  		switch node.GeneratedIdentity.GeneratedAsIdentityType {
  1958  		case GeneratedAlways:
  1959  			generatedConstraint = pretty.Keyword("GENERATED ALWAYS AS IDENTITY")
  1960  		case GeneratedByDefault:
  1961  			generatedConstraint = pretty.Keyword("GENERATED BY DEFAULT AS IDENTITY")
  1962  		}
  1963  		clauses = append(clauses, generatedConstraint)
  1964  		if node.GeneratedIdentity.SeqOptions != nil {
  1965  			const prettyFlags = FmtShowPasswords | FmtParsable
  1966  			curGenSeqOpts := node.GeneratedIdentity.SeqOptions
  1967  			txt := AsStringWithFlags(&curGenSeqOpts, prettyFlags)
  1968  			bracketedTxt := p.bracket("(", pretty.Text(strings.TrimSpace(txt)), ")")
  1969  			clauses = append(clauses, bracketedTxt)
  1970  		}
  1971  	}
  1972  
  1973  	// Column family.
  1974  	if node.HasColumnFamily() {
  1975  		d := pretty.Keyword("FAMILY")
  1976  		if node.Family.Name != "" {
  1977  			d = pretty.ConcatSpace(d, p.Doc(&node.Family.Name))
  1978  		}
  1979  		if node.Family.Create {
  1980  			c := pretty.Keyword("CREATE")
  1981  			if node.Family.IfNotExists {
  1982  				c = pretty.ConcatSpace(c, pretty.Keyword("IF NOT EXISTS"))
  1983  			}
  1984  			d = pretty.ConcatSpace(c, d)
  1985  		}
  1986  		clauses = append(clauses, d)
  1987  	}
  1988  
  1989  	// DEFAULT constraint.
  1990  	if node.HasDefaultExpr() {
  1991  		clauses = append(clauses, p.maybePrependConstraintName(&node.DefaultExpr.ConstraintName,
  1992  			pretty.ConcatSpace(pretty.Keyword("DEFAULT"), p.Doc(node.DefaultExpr.Expr))))
  1993  	}
  1994  
  1995  	// ON UPDATE expression.
  1996  	if node.HasOnUpdateExpr() {
  1997  		clauses = append(clauses, p.maybePrependConstraintName(&node.OnUpdateExpr.ConstraintName,
  1998  			pretty.ConcatSpace(pretty.Keyword("ON UPDATE"), p.Doc(node.OnUpdateExpr.Expr))))
  1999  	}
  2000  
  2001  	// [NOT] VISIBLE constraint.
  2002  	if node.Hidden {
  2003  		hiddenConstraint := pretty.Keyword("NOT VISIBLE")
  2004  		clauses = append(clauses, p.maybePrependConstraintName(&node.Nullable.ConstraintName, hiddenConstraint))
  2005  	}
  2006  
  2007  	// NULL/NOT NULL constraint.
  2008  	nConstraint := pretty.Nil
  2009  	switch node.Nullable.Nullability {
  2010  	case Null:
  2011  		nConstraint = pretty.Keyword("NULL")
  2012  	case NotNull:
  2013  		nConstraint = pretty.Keyword("NOT NULL")
  2014  	}
  2015  	if nConstraint != pretty.Nil {
  2016  		clauses = append(clauses, p.maybePrependConstraintName(&node.Nullable.ConstraintName, nConstraint))
  2017  	}
  2018  
  2019  	// PRIMARY KEY / UNIQUE constraint.
  2020  	pkConstraint := pretty.Nil
  2021  	if node.PrimaryKey.IsPrimaryKey {
  2022  		pkConstraint = pretty.Keyword("PRIMARY KEY")
  2023  	} else if node.Unique.IsUnique {
  2024  		pkConstraint = pretty.Keyword("UNIQUE")
  2025  		if node.Unique.WithoutIndex {
  2026  			pkConstraint = pretty.ConcatSpace(pkConstraint, pretty.Keyword("WITHOUT INDEX"))
  2027  		}
  2028  	}
  2029  	if pkConstraint != pretty.Nil {
  2030  		clauses = append(clauses, p.maybePrependConstraintName(&node.Unique.ConstraintName, pkConstraint))
  2031  	}
  2032  
  2033  	// Always prefer to output hash sharding bucket count as a storage param.
  2034  	pkStorageParams := node.PrimaryKey.StorageParams
  2035  	if node.PrimaryKey.Sharded {
  2036  		clauses = append(clauses, pretty.Keyword("USING HASH"))
  2037  		bcStorageParam := node.PrimaryKey.StorageParams.GetVal(`bucket_count`)
  2038  		if _, ok := node.PrimaryKey.ShardBuckets.(DefaultVal); !ok && bcStorageParam == nil {
  2039  			pkStorageParams = append(
  2040  				pkStorageParams, StorageParam{
  2041  					Key:   `bucket_count`,
  2042  					Value: node.PrimaryKey.ShardBuckets,
  2043  				},
  2044  			)
  2045  		}
  2046  	}
  2047  	if len(pkStorageParams) > 0 {
  2048  		clauses = append(clauses, p.bracketKeyword(
  2049  			"WITH", " (",
  2050  			p.Doc(&pkStorageParams),
  2051  			")", "",
  2052  		))
  2053  	}
  2054  
  2055  	// CHECK expressions/constraints.
  2056  	for _, checkExpr := range node.CheckExprs {
  2057  		clauses = append(clauses, p.maybePrependConstraintName(&checkExpr.ConstraintName,
  2058  			pretty.ConcatSpace(pretty.Keyword("CHECK"), p.bracket("(", p.Doc(checkExpr.Expr), ")"))))
  2059  	}
  2060  
  2061  	// FK constraints.
  2062  	if node.HasFKConstraint() {
  2063  		fkHead := pretty.ConcatSpace(pretty.Keyword("REFERENCES"), p.Doc(node.References.Table))
  2064  		if node.References.Col != "" {
  2065  			fkHead = pretty.ConcatSpace(fkHead, p.bracket("(", p.Doc(&node.References.Col), ")"))
  2066  		}
  2067  		fkDetails := make([]pretty.Doc, 0, 2)
  2068  		// We omit MATCH SIMPLE because it is the default.
  2069  		if node.References.Match != MatchSimple {
  2070  			fkDetails = append(fkDetails, pretty.Keyword(node.References.Match.String()))
  2071  		}
  2072  		if ref := p.Doc(&node.References.Actions); ref != pretty.Nil {
  2073  			fkDetails = append(fkDetails, ref)
  2074  		}
  2075  		fk := fkHead
  2076  		if len(fkDetails) > 0 {
  2077  			fk = p.nestUnder(fk, pretty.Group(pretty.Stack(fkDetails...)))
  2078  		}
  2079  		clauses = append(clauses, p.maybePrependConstraintName(&node.References.ConstraintName, fk))
  2080  	}
  2081  
  2082  	// Prevents an additional space from being appended at the end of every column
  2083  	// name in the case of CREATE TABLE ... AS query. The additional space is
  2084  	// being caused due to the absence of column type qualifiers in CTAS queries.
  2085  	//
  2086  	// TODO(adityamaru): Consult someone with more knowledge about the pretty
  2087  	// printer architecture to find a cleaner solution.
  2088  	var tblRow pretty.TableRow
  2089  	if node.Type == nil {
  2090  		tblRow = pretty.TableRow{
  2091  			Label: node.Name.String(),
  2092  			Doc:   pretty.Stack(clauses...),
  2093  		}
  2094  	} else {
  2095  		tblRow = pretty.TableRow{
  2096  			Label: node.Name.String(),
  2097  			Doc:   pretty.Group(pretty.Stack(clauses...)),
  2098  		}
  2099  	}
  2100  
  2101  	return tblRow
  2102  }
  2103  
  2104  func (p *PrettyCfg) formatType(typ ResolvableTypeReference) pretty.Doc {
  2105  	ctx := NewFmtCtx(p.fmtFlags())
  2106  	ctx.FormatTypeReference(typ)
  2107  	return pretty.Text(strings.TrimSpace(ctx.String()))
  2108  }
  2109  
  2110  func (node *CheckConstraintTableDef) doc(p *PrettyCfg) pretty.Doc {
  2111  	// Final layout:
  2112  	//
  2113  	// CONSTRAINT name
  2114  	//    CHECK (...)
  2115  	//
  2116  	// or (no constraint name):
  2117  	//
  2118  	// CHECK (...)
  2119  	//
  2120  	d := pretty.ConcatSpace(pretty.Keyword("CHECK"),
  2121  		p.bracket("(", p.Doc(node.Expr), ")"))
  2122  
  2123  	if node.Name != "" {
  2124  		d = p.nestUnder(
  2125  			pretty.ConcatSpace(
  2126  				pretty.Keyword("CONSTRAINT"),
  2127  				p.Doc(&node.Name),
  2128  			),
  2129  			d,
  2130  		)
  2131  	}
  2132  	return d
  2133  }
  2134  
  2135  func (node *ReferenceActions) doc(p *PrettyCfg) pretty.Doc {
  2136  	var docs []pretty.Doc
  2137  	if node.Delete != NoAction {
  2138  		docs = append(docs,
  2139  			pretty.Keyword("ON DELETE"),
  2140  			pretty.Keyword(node.Delete.String()),
  2141  		)
  2142  	}
  2143  	if node.Update != NoAction {
  2144  		docs = append(docs,
  2145  			pretty.Keyword("ON UPDATE"),
  2146  			pretty.Keyword(node.Update.String()),
  2147  		)
  2148  	}
  2149  	return pretty.Fold(pretty.ConcatSpace, docs...)
  2150  }
  2151  
  2152  func (node *Backup) doc(p *PrettyCfg) pretty.Doc {
  2153  	items := make([]pretty.TableRow, 0, 7)
  2154  
  2155  	items = append(items, p.row("BACKUP", pretty.Nil))
  2156  	if node.Targets != nil {
  2157  		items = append(items, node.Targets.docRow(p))
  2158  	}
  2159  	if node.Nested {
  2160  		if node.Subdir != nil {
  2161  			items = append(items, p.row("INTO ", p.Doc(node.Subdir)))
  2162  			items = append(items, p.row(" IN ", p.Doc(&node.To)))
  2163  		} else if node.AppendToLatest {
  2164  			items = append(items, p.row("INTO LATEST IN", p.Doc(&node.To)))
  2165  		} else {
  2166  			items = append(items, p.row("INTO", p.Doc(&node.To)))
  2167  		}
  2168  	} else {
  2169  		items = append(items, p.row("TO", p.Doc(&node.To)))
  2170  	}
  2171  
  2172  	if node.AsOf.Expr != nil {
  2173  		items = append(items, node.AsOf.docRow(p))
  2174  	}
  2175  	if node.IncrementalFrom != nil {
  2176  		items = append(items, p.row("INCREMENTAL FROM", p.Doc(&node.IncrementalFrom)))
  2177  	}
  2178  	if !node.Options.IsDefault() {
  2179  		items = append(items, p.row("WITH", p.Doc(&node.Options)))
  2180  	}
  2181  	return p.rlTable(items...)
  2182  }
  2183  
  2184  func (node *Restore) doc(p *PrettyCfg) pretty.Doc {
  2185  	items := make([]pretty.TableRow, 0, 6)
  2186  
  2187  	items = append(items, p.row("RESTORE", pretty.Nil))
  2188  	if node.DescriptorCoverage == RequestedDescriptors {
  2189  		items = append(items, node.Targets.docRow(p))
  2190  	}
  2191  	from := make([]pretty.Doc, len(node.From))
  2192  	for i := range node.From {
  2193  		from[i] = p.Doc(&node.From[i])
  2194  	}
  2195  	if node.Subdir != nil {
  2196  		items = append(items, p.row("FROM", p.Doc(node.Subdir)))
  2197  		items = append(items, p.row("IN", p.commaSeparated(from...)))
  2198  	} else {
  2199  		items = append(items, p.row("FROM", p.commaSeparated(from...)))
  2200  	}
  2201  
  2202  	if node.AsOf.Expr != nil {
  2203  		items = append(items, node.AsOf.docRow(p))
  2204  	}
  2205  	if !node.Options.IsDefault() {
  2206  		items = append(items, p.row("WITH", p.Doc(&node.Options)))
  2207  	}
  2208  	return p.rlTable(items...)
  2209  }
  2210  
  2211  func (node *BackupTargetList) doc(p *PrettyCfg) pretty.Doc {
  2212  	return p.unrow(node.docRow(p))
  2213  }
  2214  
  2215  func (node *BackupTargetList) docRow(p *PrettyCfg) pretty.TableRow {
  2216  	if node.Databases != nil {
  2217  		return p.row("DATABASE", p.Doc(&node.Databases))
  2218  	}
  2219  	if node.TenantID.Specified {
  2220  		return p.row("TENANT", p.Doc(&node.TenantID))
  2221  	}
  2222  	if node.Tables.SequenceOnly {
  2223  		return p.row("SEQUENCE", p.Doc(&node.Tables.TablePatterns))
  2224  	}
  2225  	return p.row("TABLE", p.Doc(&node.Tables.TablePatterns))
  2226  }
  2227  
  2228  func (node *GrantTargetList) doc(p *PrettyCfg) pretty.Doc {
  2229  	return p.unrow(node.docRow(p))
  2230  }
  2231  
  2232  func (node *GrantTargetList) docRow(p *PrettyCfg) pretty.TableRow {
  2233  	if node.Databases != nil {
  2234  		return p.row("DATABASE", p.Doc(&node.Databases))
  2235  	}
  2236  	if node.Tables.SequenceOnly {
  2237  		return p.row("SEQUENCE", p.Doc(&node.Tables.TablePatterns))
  2238  	}
  2239  	if node.ExternalConnections != nil {
  2240  		return p.row("EXTERNAL CONNECTION", p.Doc(&node.ExternalConnections))
  2241  	}
  2242  	return p.row("TABLE", p.Doc(&node.Tables.TablePatterns))
  2243  }
  2244  
  2245  func (node *AsOfClause) doc(p *PrettyCfg) pretty.Doc {
  2246  	return p.unrow(node.docRow(p))
  2247  }
  2248  
  2249  func (node *AsOfClause) docRow(p *PrettyCfg) pretty.TableRow {
  2250  	return p.row("AS OF SYSTEM TIME", p.Doc(node.Expr))
  2251  }
  2252  
  2253  func (node *KVOptions) doc(p *PrettyCfg) pretty.Doc {
  2254  	var opts []pretty.Doc
  2255  	for _, opt := range *node {
  2256  		d := p.Doc(&opt.Key)
  2257  		if opt.Value != nil {
  2258  			d = pretty.Fold(pretty.ConcatSpace,
  2259  				d,
  2260  				pretty.Text("="),
  2261  				p.Doc(opt.Value),
  2262  			)
  2263  		}
  2264  		opts = append(opts, d)
  2265  	}
  2266  	return p.commaSeparated(opts...)
  2267  }
  2268  
  2269  func (node *Import) doc(p *PrettyCfg) pretty.Doc {
  2270  	items := make([]pretty.TableRow, 0, 5)
  2271  	items = append(items, p.row("IMPORT", pretty.Nil))
  2272  
  2273  	if node.Bundle {
  2274  		if node.Table != nil {
  2275  			items = append(items, p.row("TABLE", p.Doc(node.Table)))
  2276  			items = append(items, p.row("FROM", pretty.Nil))
  2277  		}
  2278  		items = append(items, p.row(node.FileFormat, p.Doc(&node.Files)))
  2279  	} else if node.Into {
  2280  		into := p.Doc(node.Table)
  2281  		if node.IntoCols != nil {
  2282  			into = p.nestUnder(into, p.bracket("(", p.Doc(&node.IntoCols), ")"))
  2283  		}
  2284  		items = append(items, p.row("INTO", into))
  2285  		data := p.bracketKeyword(
  2286  			"DATA", " (",
  2287  			p.Doc(&node.Files),
  2288  			")", "",
  2289  		)
  2290  		items = append(items, p.row(node.FileFormat, data))
  2291  	}
  2292  
  2293  	if node.Options != nil {
  2294  		items = append(items, p.row("WITH", p.Doc(&node.Options)))
  2295  	}
  2296  	return p.rlTable(items...)
  2297  }
  2298  
  2299  func (node *Export) doc(p *PrettyCfg) pretty.Doc {
  2300  	items := make([]pretty.TableRow, 0, 4)
  2301  	items = append(items, p.row("EXPORT", pretty.Nil))
  2302  	items = append(items, p.row("INTO "+node.FileFormat, p.Doc(node.File)))
  2303  	if node.Options != nil {
  2304  		items = append(items, p.row("WITH", p.Doc(&node.Options)))
  2305  	}
  2306  	items = append(items, p.row("FROM", p.Doc(node.Query)))
  2307  	return p.rlTable(items...)
  2308  }
  2309  
  2310  func (node *NotExpr) doc(p *PrettyCfg) pretty.Doc {
  2311  	return p.nestUnder(
  2312  		pretty.Keyword("NOT"),
  2313  		p.exprDocWithParen(node.Expr),
  2314  	)
  2315  }
  2316  
  2317  func (node *IsNullExpr) doc(p *PrettyCfg) pretty.Doc {
  2318  	return pretty.ConcatSpace(
  2319  		p.exprDocWithParen(node.Expr),
  2320  		pretty.Keyword("IS NULL"),
  2321  	)
  2322  }
  2323  
  2324  func (node *IsNotNullExpr) doc(p *PrettyCfg) pretty.Doc {
  2325  	return pretty.ConcatSpace(
  2326  		p.exprDocWithParen(node.Expr),
  2327  		pretty.Keyword("IS NOT NULL"),
  2328  	)
  2329  }
  2330  
  2331  func (node *CoalesceExpr) doc(p *PrettyCfg) pretty.Doc {
  2332  	return p.bracketKeyword(
  2333  		node.Name, "(",
  2334  		p.Doc(&node.Exprs),
  2335  		")", "",
  2336  	)
  2337  }
  2338  
  2339  func (node *AlterTable) doc(p *PrettyCfg) pretty.Doc {
  2340  	title := pretty.Keyword("ALTER TABLE")
  2341  	if node.IfExists {
  2342  		title = pretty.ConcatSpace(title, pretty.Keyword("IF EXISTS"))
  2343  	}
  2344  	title = pretty.ConcatSpace(title, p.Doc(node.Table))
  2345  	return p.nestUnder(
  2346  		title,
  2347  		p.Doc(&node.Cmds),
  2348  	)
  2349  }
  2350  
  2351  func (node *AlterTableCmds) doc(p *PrettyCfg) pretty.Doc {
  2352  	cmds := make([]pretty.Doc, len(*node))
  2353  	for i, c := range *node {
  2354  		cmds[i] = p.Doc(c)
  2355  	}
  2356  	return p.commaSeparated(cmds...)
  2357  }
  2358  
  2359  func (node *AlterTableAddColumn) doc(p *PrettyCfg) pretty.Doc {
  2360  	title := pretty.Keyword("ADD COLUMN")
  2361  	if node.IfNotExists {
  2362  		title = pretty.ConcatSpace(title, pretty.Keyword("IF NOT EXISTS"))
  2363  	}
  2364  	return p.nestUnder(
  2365  		title,
  2366  		p.Doc(node.ColumnDef),
  2367  	)
  2368  }
  2369  
  2370  func (node *Prepare) doc(p *PrettyCfg) pretty.Doc {
  2371  	return p.rlTable(node.docTable(p)...)
  2372  }
  2373  
  2374  func (node *Prepare) docTable(p *PrettyCfg) []pretty.TableRow {
  2375  	name := p.Doc(&node.Name)
  2376  	if len(node.Types) > 0 {
  2377  		typs := make([]pretty.Doc, len(node.Types))
  2378  		for i, t := range node.Types {
  2379  			typs[i] = p.formatType(t)
  2380  		}
  2381  		name = pretty.ConcatSpace(name,
  2382  			p.bracket("(", p.commaSeparated(typs...), ")"),
  2383  		)
  2384  	}
  2385  	return []pretty.TableRow{
  2386  		p.row("PREPARE", name),
  2387  		p.row("AS", p.Doc(node.Statement)),
  2388  	}
  2389  }
  2390  
  2391  func (node *Execute) doc(p *PrettyCfg) pretty.Doc {
  2392  	return p.rlTable(node.docTable(p)...)
  2393  }
  2394  
  2395  func (node *Execute) docTable(p *PrettyCfg) []pretty.TableRow {
  2396  	name := p.Doc(&node.Name)
  2397  	if len(node.Params) > 0 {
  2398  		name = pretty.ConcatSpace(
  2399  			name,
  2400  			p.bracket("(", p.Doc(&node.Params), ")"),
  2401  		)
  2402  	}
  2403  	rows := []pretty.TableRow{p.row("EXECUTE", name)}
  2404  	if node.DiscardRows {
  2405  		rows = append(rows, p.row("", pretty.Keyword("DISCARD ROWS")))
  2406  	}
  2407  	return rows
  2408  }
  2409  
  2410  func (node *AnnotateTypeExpr) doc(p *PrettyCfg) pretty.Doc {
  2411  	if node.SyntaxMode == AnnotateShort {
  2412  		if typ, ok := GetStaticallyKnownType(node.Type); ok {
  2413  			switch typ.Family() {
  2414  			case types.JsonFamily:
  2415  				if sv, ok := node.Expr.(*StrVal); ok && p.JSONFmt {
  2416  					return p.jsonCast(sv, ":::", typ)
  2417  				}
  2418  			}
  2419  		}
  2420  	}
  2421  	return p.docAsString(node)
  2422  }
  2423  
  2424  func (node *DeclareCursor) docTable(p *PrettyCfg) []pretty.TableRow {
  2425  	optionsRow := pretty.Nil
  2426  	if node.Binary {
  2427  		optionsRow = pretty.ConcatSpace(optionsRow, pretty.Keyword("BINARY"))
  2428  	}
  2429  	if node.Sensitivity != UnspecifiedSensitivity {
  2430  		optionsRow = pretty.ConcatSpace(optionsRow, pretty.Keyword(node.Sensitivity.String()))
  2431  	}
  2432  	if node.Scroll != UnspecifiedScroll {
  2433  		optionsRow = pretty.ConcatSpace(optionsRow, pretty.Keyword(node.Scroll.String()))
  2434  	}
  2435  	cursorRow := pretty.Nil
  2436  	if node.Hold {
  2437  		cursorRow = pretty.ConcatSpace(cursorRow, pretty.Keyword("WITH HOLD"))
  2438  	}
  2439  	return []pretty.TableRow{
  2440  		p.row("DECLARE", pretty.ConcatLine(p.Doc(&node.Name), optionsRow)),
  2441  		p.row("CURSOR", cursorRow),
  2442  		p.row("FOR", node.Select.doc(p)),
  2443  	}
  2444  }
  2445  
  2446  func (node *DeclareCursor) doc(p *PrettyCfg) pretty.Doc {
  2447  	return p.rlTable(node.docTable(p)...)
  2448  }
  2449  
  2450  func (node *CursorStmt) doc(p *PrettyCfg) pretty.Doc {
  2451  	ret := pretty.Nil
  2452  	fetchType := node.FetchType.String()
  2453  	if fetchType != "" {
  2454  		ret = pretty.ConcatSpace(ret, pretty.Keyword(fetchType))
  2455  	}
  2456  	if node.FetchType.HasCount() {
  2457  		ret = pretty.ConcatSpace(ret, pretty.Text(strconv.Itoa(int(node.Count))))
  2458  	}
  2459  	return pretty.Fold(pretty.ConcatSpace,
  2460  		ret,
  2461  		pretty.Keyword("FROM"),
  2462  		p.Doc(&node.Name),
  2463  	)
  2464  }
  2465  
  2466  func (node *FetchCursor) doc(p *PrettyCfg) pretty.Doc {
  2467  	return pretty.ConcatSpace(pretty.Keyword("FETCH"), node.CursorStmt.doc(p))
  2468  }
  2469  
  2470  func (node *MoveCursor) doc(p *PrettyCfg) pretty.Doc {
  2471  	return pretty.ConcatSpace(pretty.Keyword("MOVE"), node.CursorStmt.doc(p))
  2472  }
  2473  
  2474  func (node *CloseCursor) doc(p *PrettyCfg) pretty.Doc {
  2475  	close := pretty.Keyword("CLOSE")
  2476  	if node.All {
  2477  		return pretty.ConcatSpace(close, pretty.Keyword("ALL"))
  2478  	}
  2479  	return pretty.ConcatSpace(close, p.Doc(&node.Name))
  2480  }
  2481  
  2482  // jsonCast attempts to pretty print a string that is cast or asserted as JSON.
  2483  func (p *PrettyCfg) jsonCast(sv *StrVal, op string, typ *types.T) pretty.Doc {
  2484  	return pretty.Fold(pretty.Concat,
  2485  		p.jsonString(sv.RawString()),
  2486  		pretty.Text(op),
  2487  		p.formatType(typ),
  2488  	)
  2489  }
  2490  
  2491  // jsonString parses s as JSON and pretty prints it.
  2492  func (p *PrettyCfg) jsonString(s string) pretty.Doc {
  2493  	j, err := json.ParseJSON(s)
  2494  	if err != nil {
  2495  		return pretty.Text(s)
  2496  	}
  2497  	return p.bracket(`'`, p.jsonNode(j), `'`)
  2498  }
  2499  
  2500  // jsonNode pretty prints a JSON node.
  2501  func (p *PrettyCfg) jsonNode(j json.JSON) pretty.Doc {
  2502  	// Figure out what type this is.
  2503  	if it, _ := j.ObjectIter(); it != nil {
  2504  		// Object.
  2505  		elems := make([]pretty.Doc, 0, j.Len())
  2506  		for it.Next() {
  2507  			elems = append(elems, p.nestUnder(
  2508  				pretty.Concat(
  2509  					pretty.Text(json.FromString(it.Key()).String()),
  2510  					pretty.Text(`:`),
  2511  				),
  2512  				p.jsonNode(it.Value()),
  2513  			))
  2514  		}
  2515  		return p.bracket("{", p.commaSeparated(elems...), "}")
  2516  	} else if n := j.Len(); n > 0 {
  2517  		// Non-empty array.
  2518  		elems := make([]pretty.Doc, n)
  2519  		for i := 0; i < n; i++ {
  2520  			elem, err := j.FetchValIdx(i)
  2521  			if err != nil {
  2522  				return pretty.Text(j.String())
  2523  			}
  2524  			elems[i] = p.jsonNode(elem)
  2525  		}
  2526  		return p.bracket("[", p.commaSeparated(elems...), "]")
  2527  	}
  2528  	// Other.
  2529  	return pretty.Text(j.String())
  2530  }