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