github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/create.go (about) 1 // Copyright 2012, Google Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in licenses/BSD-vitess.txt. 4 5 // Portions of this file are additionally subject to the following 6 // license and copyright. 7 // 8 // Copyright 2015 The Cockroach Authors. 9 // 10 // Use of this software is governed by the Business Source License 11 // included in the file licenses/BSL.txt. 12 // 13 // As of the Change Date specified in that file, in accordance with 14 // the Business Source License, use of this software will be governed 15 // by the Apache License, Version 2.0, included in the file 16 // licenses/APL.txt. 17 18 // This code was derived from https://github.com/youtube/vitess. 19 20 package tree 21 22 import ( 23 "fmt" 24 "strconv" 25 "strings" 26 27 "github.com/cockroachdb/cockroach/pkg/sql/lex" 28 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 29 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 30 "github.com/cockroachdb/cockroach/pkg/sql/roleoption" 31 "github.com/cockroachdb/cockroach/pkg/sql/types" 32 "github.com/cockroachdb/errors" 33 "golang.org/x/text/language" 34 ) 35 36 // CreateDatabase represents a CREATE DATABASE statement. 37 type CreateDatabase struct { 38 IfNotExists bool 39 Name Name 40 Template string 41 Encoding string 42 Collate string 43 CType string 44 } 45 46 // Format implements the NodeFormatter interface. 47 func (node *CreateDatabase) Format(ctx *FmtCtx) { 48 ctx.WriteString("CREATE DATABASE ") 49 if node.IfNotExists { 50 ctx.WriteString("IF NOT EXISTS ") 51 } 52 ctx.FormatNode(&node.Name) 53 if node.Template != "" { 54 ctx.WriteString(" TEMPLATE = ") 55 lex.EncodeSQLStringWithFlags(&ctx.Buffer, node.Template, ctx.flags.EncodeFlags()) 56 } 57 if node.Encoding != "" { 58 ctx.WriteString(" ENCODING = ") 59 lex.EncodeSQLStringWithFlags(&ctx.Buffer, node.Encoding, ctx.flags.EncodeFlags()) 60 } 61 if node.Collate != "" { 62 ctx.WriteString(" LC_COLLATE = ") 63 lex.EncodeSQLStringWithFlags(&ctx.Buffer, node.Collate, ctx.flags.EncodeFlags()) 64 } 65 if node.CType != "" { 66 ctx.WriteString(" LC_CTYPE = ") 67 lex.EncodeSQLStringWithFlags(&ctx.Buffer, node.CType, ctx.flags.EncodeFlags()) 68 } 69 } 70 71 // IndexElem represents a column with a direction in a CREATE INDEX statement. 72 type IndexElem struct { 73 Column Name 74 Direction Direction 75 NullsOrder NullsOrder 76 } 77 78 // Format implements the NodeFormatter interface. 79 func (node *IndexElem) Format(ctx *FmtCtx) { 80 ctx.FormatNode(&node.Column) 81 if node.Direction != DefaultDirection { 82 ctx.WriteByte(' ') 83 ctx.WriteString(node.Direction.String()) 84 } 85 if node.NullsOrder != DefaultNullsOrder { 86 ctx.WriteByte(' ') 87 ctx.WriteString(node.NullsOrder.String()) 88 } 89 } 90 91 // IndexElemList is list of IndexElem. 92 type IndexElemList []IndexElem 93 94 // Format pretty-prints the contained names separated by commas. 95 // Format implements the NodeFormatter interface. 96 func (l *IndexElemList) Format(ctx *FmtCtx) { 97 for i := range *l { 98 if i > 0 { 99 ctx.WriteString(", ") 100 } 101 ctx.FormatNode(&(*l)[i]) 102 } 103 } 104 105 // CreateIndex represents a CREATE INDEX statement. 106 type CreateIndex struct { 107 Name Name 108 Table TableName 109 Unique bool 110 Inverted bool 111 IfNotExists bool 112 Columns IndexElemList 113 Sharded *ShardedIndexDef 114 // Extra columns to be stored together with the indexed ones as an optimization 115 // for improved reading performance. 116 Storing NameList 117 Interleave *InterleaveDef 118 PartitionBy *PartitionBy 119 Predicate Expr 120 Concurrently bool 121 } 122 123 // Format implements the NodeFormatter interface. 124 func (node *CreateIndex) Format(ctx *FmtCtx) { 125 ctx.WriteString("CREATE ") 126 if node.Unique { 127 ctx.WriteString("UNIQUE ") 128 } 129 if node.Inverted && !ctx.HasFlags(FmtPGIndexDef) { 130 ctx.WriteString("INVERTED ") 131 } 132 ctx.WriteString("INDEX ") 133 if node.Concurrently { 134 ctx.WriteString("CONCURRENTLY ") 135 } 136 if node.IfNotExists { 137 ctx.WriteString("IF NOT EXISTS ") 138 } 139 if node.Name != "" { 140 ctx.FormatNode(&node.Name) 141 ctx.WriteByte(' ') 142 } 143 ctx.WriteString("ON ") 144 ctx.FormatNode(&node.Table) 145 if ctx.HasFlags(FmtPGIndexDef) { 146 ctx.WriteString(" USING") 147 if node.Inverted { 148 ctx.WriteString(" gin") 149 } else { 150 ctx.WriteString(" btree") 151 } 152 } 153 ctx.WriteString(" (") 154 ctx.FormatNode(&node.Columns) 155 ctx.WriteByte(')') 156 if node.Sharded != nil { 157 ctx.FormatNode(node.Sharded) 158 } 159 if len(node.Storing) > 0 { 160 ctx.WriteString(" STORING (") 161 ctx.FormatNode(&node.Storing) 162 ctx.WriteByte(')') 163 } 164 if node.Interleave != nil { 165 ctx.FormatNode(node.Interleave) 166 } 167 if node.PartitionBy != nil { 168 ctx.FormatNode(node.PartitionBy) 169 } 170 if node.Predicate != nil { 171 ctx.WriteString(" WHERE ") 172 ctx.FormatNode(node.Predicate) 173 } 174 } 175 176 // CreateTypeVariety represents a particular variety of user defined types. 177 type CreateTypeVariety int 178 179 //go:generate stringer -type=CreateTypeVariety 180 const ( 181 _ CreateTypeVariety = iota 182 // Enum represents an ENUM user defined type. 183 Enum 184 // Composite represents a composite user defined type. 185 Composite 186 // Range represents a RANGE user defined type. 187 Range 188 // Base represents a base user defined type. 189 Base 190 // Shell represents a shell user defined type. 191 Shell 192 // Domain represents a DOMAIN user defined type. 193 Domain 194 ) 195 196 // CreateType represents a CREATE TYPE statement. 197 type CreateType struct { 198 TypeName *UnresolvedObjectName 199 Variety CreateTypeVariety 200 // EnumLabels is set when this represents a CREATE TYPE ... AS ENUM statement. 201 EnumLabels []string 202 } 203 204 var _ Statement = &CreateType{} 205 206 // Format implements the NodeFormatter interface. 207 func (node *CreateType) Format(ctx *FmtCtx) { 208 ctx.WriteString("CREATE TYPE ") 209 ctx.WriteString(node.TypeName.String()) 210 ctx.WriteString(" ") 211 switch node.Variety { 212 case Enum: 213 ctx.WriteString("AS ENUM (") 214 for i := range node.EnumLabels { 215 if i > 0 { 216 ctx.WriteString(", ") 217 } 218 lex.EncodeSQLString(&ctx.Buffer, node.EnumLabels[i]) 219 } 220 ctx.WriteString(")") 221 } 222 } 223 224 func (node *CreateType) String() string { 225 return AsString(node) 226 } 227 228 // TableDef represents a column, index or constraint definition within a CREATE 229 // TABLE statement. 230 type TableDef interface { 231 NodeFormatter 232 // Placeholder function to ensure that only desired types (*TableDef) conform 233 // to the TableDef interface. 234 tableDef() 235 } 236 237 func (*ColumnTableDef) tableDef() {} 238 func (*IndexTableDef) tableDef() {} 239 func (*FamilyTableDef) tableDef() {} 240 func (*ForeignKeyConstraintTableDef) tableDef() {} 241 func (*CheckConstraintTableDef) tableDef() {} 242 func (*LikeTableDef) tableDef() {} 243 244 // TableDefs represents a list of table definitions. 245 type TableDefs []TableDef 246 247 // Format implements the NodeFormatter interface. 248 func (node *TableDefs) Format(ctx *FmtCtx) { 249 for i, n := range *node { 250 if i > 0 { 251 ctx.WriteString(", ") 252 } 253 ctx.FormatNode(n) 254 } 255 } 256 257 // Nullability represents either NULL, NOT NULL or an unspecified value (silent 258 // NULL). 259 type Nullability int 260 261 // The values for NullType. 262 const ( 263 NotNull Nullability = iota 264 Null 265 SilentNull 266 ) 267 268 // ColumnTableDef represents a column definition within a CREATE TABLE 269 // statement. 270 type ColumnTableDef struct { 271 Name Name 272 Type ResolvableTypeReference 273 IsSerial bool 274 Nullable struct { 275 Nullability Nullability 276 ConstraintName Name 277 } 278 PrimaryKey struct { 279 IsPrimaryKey bool 280 Sharded bool 281 ShardBuckets Expr 282 } 283 Unique bool 284 UniqueConstraintName Name 285 DefaultExpr struct { 286 Expr Expr 287 ConstraintName Name 288 } 289 CheckExprs []ColumnTableDefCheckExpr 290 References struct { 291 Table *TableName 292 Col Name 293 ConstraintName Name 294 Actions ReferenceActions 295 Match CompositeKeyMatchMethod 296 } 297 Computed struct { 298 Computed bool 299 Expr Expr 300 } 301 Family struct { 302 Name Name 303 Create bool 304 IfNotExists bool 305 } 306 } 307 308 // ColumnTableDefCheckExpr represents a check constraint on a column definition 309 // within a CREATE TABLE statement. 310 type ColumnTableDefCheckExpr struct { 311 Expr Expr 312 ConstraintName Name 313 } 314 315 func processCollationOnType( 316 name Name, ref ResolvableTypeReference, c ColumnCollation, 317 ) (*types.T, error) { 318 // At the moment, only string types can be collated. User defined types 319 // like enums don't support collations, so check this at parse time. 320 typ, ok := GetStaticallyKnownType(ref) 321 if !ok { 322 return nil, pgerror.Newf(pgcode.DatatypeMismatch, 323 "COLLATE declaration for non-string-typed column %q", name) 324 } 325 switch typ.Family() { 326 case types.StringFamily: 327 return types.MakeCollatedString(typ, string(c)), nil 328 case types.CollatedStringFamily: 329 return nil, pgerror.Newf(pgcode.Syntax, 330 "multiple COLLATE declarations for column %q", name) 331 case types.ArrayFamily: 332 elemTyp, err := processCollationOnType(name, typ.ArrayContents(), c) 333 if err != nil { 334 return nil, err 335 } 336 return types.MakeArray(elemTyp), nil 337 default: 338 return nil, pgerror.Newf(pgcode.DatatypeMismatch, 339 "COLLATE declaration for non-string-typed column %q", name) 340 } 341 } 342 343 // NewColumnTableDef constructs a column definition for a CreateTable statement. 344 func NewColumnTableDef( 345 name Name, 346 typRef ResolvableTypeReference, 347 isSerial bool, 348 qualifications []NamedColumnQualification, 349 ) (*ColumnTableDef, error) { 350 d := &ColumnTableDef{ 351 Name: name, 352 Type: typRef, 353 IsSerial: isSerial, 354 } 355 d.Nullable.Nullability = SilentNull 356 for _, c := range qualifications { 357 switch t := c.Qualification.(type) { 358 case ColumnCollation: 359 locale := string(t) 360 _, err := language.Parse(locale) 361 if err != nil { 362 return nil, pgerror.Wrapf(err, pgcode.Syntax, "invalid locale %s", locale) 363 } 364 collatedTyp, err := processCollationOnType(name, d.Type, t) 365 if err != nil { 366 return nil, err 367 } 368 d.Type = collatedTyp 369 case *ColumnDefault: 370 if d.HasDefaultExpr() { 371 return nil, pgerror.Newf(pgcode.Syntax, 372 "multiple default values specified for column %q", name) 373 } 374 d.DefaultExpr.Expr = t.Expr 375 d.DefaultExpr.ConstraintName = c.Name 376 case NotNullConstraint: 377 if d.Nullable.Nullability == Null { 378 return nil, pgerror.Newf(pgcode.Syntax, 379 "conflicting NULL/NOT NULL declarations for column %q", name) 380 } 381 d.Nullable.Nullability = NotNull 382 d.Nullable.ConstraintName = c.Name 383 case NullConstraint: 384 if d.Nullable.Nullability == NotNull { 385 return nil, pgerror.Newf(pgcode.Syntax, 386 "conflicting NULL/NOT NULL declarations for column %q", name) 387 } 388 d.Nullable.Nullability = Null 389 d.Nullable.ConstraintName = c.Name 390 case PrimaryKeyConstraint: 391 d.PrimaryKey.IsPrimaryKey = true 392 d.UniqueConstraintName = c.Name 393 case ShardedPrimaryKeyConstraint: 394 d.PrimaryKey.IsPrimaryKey = true 395 constraint := c.Qualification.(ShardedPrimaryKeyConstraint) 396 d.PrimaryKey.Sharded = true 397 d.PrimaryKey.ShardBuckets = constraint.ShardBuckets 398 d.UniqueConstraintName = c.Name 399 case UniqueConstraint: 400 d.Unique = true 401 d.UniqueConstraintName = c.Name 402 case *ColumnCheckConstraint: 403 d.CheckExprs = append(d.CheckExprs, ColumnTableDefCheckExpr{ 404 Expr: t.Expr, 405 ConstraintName: c.Name, 406 }) 407 case *ColumnFKConstraint: 408 if d.HasFKConstraint() { 409 return nil, pgerror.Newf(pgcode.InvalidTableDefinition, 410 "multiple foreign key constraints specified for column %q", name) 411 } 412 d.References.Table = &t.Table 413 d.References.Col = t.Col 414 d.References.ConstraintName = c.Name 415 d.References.Actions = t.Actions 416 d.References.Match = t.Match 417 case *ColumnComputedDef: 418 d.Computed.Computed = true 419 d.Computed.Expr = t.Expr 420 case *ColumnFamilyConstraint: 421 if d.HasColumnFamily() { 422 return nil, pgerror.Newf(pgcode.InvalidTableDefinition, 423 "multiple column families specified for column %q", name) 424 } 425 d.Family.Name = t.Family 426 d.Family.Create = t.Create 427 d.Family.IfNotExists = t.IfNotExists 428 default: 429 return nil, errors.AssertionFailedf("unexpected column qualification: %T", c) 430 } 431 } 432 return d, nil 433 } 434 435 // HasDefaultExpr returns if the ColumnTableDef has a default expression. 436 func (node *ColumnTableDef) HasDefaultExpr() bool { 437 return node.DefaultExpr.Expr != nil 438 } 439 440 // HasFKConstraint returns if the ColumnTableDef has a foreign key constraint. 441 func (node *ColumnTableDef) HasFKConstraint() bool { 442 return node.References.Table != nil 443 } 444 445 // IsComputed returns if the ColumnTableDef is a computed column. 446 func (node *ColumnTableDef) IsComputed() bool { 447 return node.Computed.Computed 448 } 449 450 // HasColumnFamily returns if the ColumnTableDef has a column family. 451 func (node *ColumnTableDef) HasColumnFamily() bool { 452 return node.Family.Name != "" || node.Family.Create 453 } 454 455 // Format implements the NodeFormatter interface. 456 func (node *ColumnTableDef) Format(ctx *FmtCtx) { 457 ctx.FormatNode(&node.Name) 458 459 // ColumnTableDef node type will not be specified if it represents a CREATE 460 // TABLE ... AS query. 461 if node.Type != nil { 462 ctx.WriteByte(' ') 463 ctx.WriteString(node.columnTypeString()) 464 } 465 466 if node.Nullable.Nullability != SilentNull && node.Nullable.ConstraintName != "" { 467 ctx.WriteString(" CONSTRAINT ") 468 ctx.FormatNode(&node.Nullable.ConstraintName) 469 } 470 switch node.Nullable.Nullability { 471 case Null: 472 ctx.WriteString(" NULL") 473 case NotNull: 474 ctx.WriteString(" NOT NULL") 475 } 476 if node.PrimaryKey.IsPrimaryKey || node.Unique { 477 if node.UniqueConstraintName != "" { 478 ctx.WriteString(" CONSTRAINT ") 479 ctx.FormatNode(&node.UniqueConstraintName) 480 } 481 if node.PrimaryKey.IsPrimaryKey { 482 ctx.WriteString(" PRIMARY KEY") 483 if node.PrimaryKey.Sharded { 484 ctx.WriteString(" USING HASH WITH BUCKET_COUNT=") 485 ctx.FormatNode(node.PrimaryKey.ShardBuckets) 486 } 487 } else if node.Unique { 488 ctx.WriteString(" UNIQUE") 489 } 490 } 491 if node.HasDefaultExpr() { 492 if node.DefaultExpr.ConstraintName != "" { 493 ctx.WriteString(" CONSTRAINT ") 494 ctx.FormatNode(&node.DefaultExpr.ConstraintName) 495 } 496 ctx.WriteString(" DEFAULT ") 497 ctx.FormatNode(node.DefaultExpr.Expr) 498 } 499 for _, checkExpr := range node.CheckExprs { 500 if checkExpr.ConstraintName != "" { 501 ctx.WriteString(" CONSTRAINT ") 502 ctx.FormatNode(&checkExpr.ConstraintName) 503 } 504 ctx.WriteString(" CHECK (") 505 ctx.FormatNode(checkExpr.Expr) 506 ctx.WriteByte(')') 507 } 508 if node.HasFKConstraint() { 509 if node.References.ConstraintName != "" { 510 ctx.WriteString(" CONSTRAINT ") 511 ctx.FormatNode(&node.References.ConstraintName) 512 } 513 ctx.WriteString(" REFERENCES ") 514 ctx.FormatNode(node.References.Table) 515 if node.References.Col != "" { 516 ctx.WriteString(" (") 517 ctx.FormatNode(&node.References.Col) 518 ctx.WriteByte(')') 519 } 520 if node.References.Match != MatchSimple { 521 ctx.WriteByte(' ') 522 ctx.WriteString(node.References.Match.String()) 523 } 524 ctx.FormatNode(&node.References.Actions) 525 } 526 if node.IsComputed() { 527 ctx.WriteString(" AS (") 528 ctx.FormatNode(node.Computed.Expr) 529 ctx.WriteString(") STORED") 530 } 531 if node.HasColumnFamily() { 532 if node.Family.Create { 533 ctx.WriteString(" CREATE") 534 if node.Family.IfNotExists { 535 ctx.WriteString(" IF NOT EXISTS") 536 } 537 } 538 ctx.WriteString(" FAMILY") 539 if len(node.Family.Name) > 0 { 540 ctx.WriteByte(' ') 541 ctx.FormatNode(&node.Family.Name) 542 } 543 } 544 } 545 546 func (node *ColumnTableDef) columnTypeString() string { 547 if node.IsSerial { 548 // Map INT types to SERIAL keyword. 549 // TODO (rohany): This should be pushed until type resolution occurs. 550 // However, the argument is that we deal with serial at parse time only, 551 // so we handle those cases here. 552 switch MustBeStaticallyKnownType(node.Type).Width() { 553 case 16: 554 return "SERIAL2" 555 case 32: 556 return "SERIAL4" 557 } 558 return "SERIAL8" 559 } 560 return node.Type.SQLString() 561 } 562 563 // String implements the fmt.Stringer interface. 564 func (node *ColumnTableDef) String() string { return AsString(node) } 565 566 // NamedColumnQualification wraps a NamedColumnQualification with a name. 567 type NamedColumnQualification struct { 568 Name Name 569 Qualification ColumnQualification 570 } 571 572 // ColumnQualification represents a constraint on a column. 573 type ColumnQualification interface { 574 columnQualification() 575 } 576 577 func (ColumnCollation) columnQualification() {} 578 func (*ColumnDefault) columnQualification() {} 579 func (NotNullConstraint) columnQualification() {} 580 func (NullConstraint) columnQualification() {} 581 func (PrimaryKeyConstraint) columnQualification() {} 582 func (ShardedPrimaryKeyConstraint) columnQualification() {} 583 func (UniqueConstraint) columnQualification() {} 584 func (*ColumnCheckConstraint) columnQualification() {} 585 func (*ColumnComputedDef) columnQualification() {} 586 func (*ColumnFKConstraint) columnQualification() {} 587 func (*ColumnFamilyConstraint) columnQualification() {} 588 589 // ColumnCollation represents a COLLATE clause for a column. 590 type ColumnCollation string 591 592 // ColumnDefault represents a DEFAULT clause for a column. 593 type ColumnDefault struct { 594 Expr Expr 595 } 596 597 // NotNullConstraint represents NOT NULL on a column. 598 type NotNullConstraint struct{} 599 600 // NullConstraint represents NULL on a column. 601 type NullConstraint struct{} 602 603 // PrimaryKeyConstraint represents PRIMARY KEY on a column. 604 type PrimaryKeyConstraint struct{} 605 606 // ShardedPrimaryKeyConstraint represents `PRIMARY KEY .. USING HASH..` 607 // on a column. 608 type ShardedPrimaryKeyConstraint struct { 609 Sharded bool 610 ShardBuckets Expr 611 } 612 613 // UniqueConstraint represents UNIQUE on a column. 614 type UniqueConstraint struct{} 615 616 // ColumnCheckConstraint represents either a check on a column. 617 type ColumnCheckConstraint struct { 618 Expr Expr 619 } 620 621 // ColumnFKConstraint represents a FK-constaint on a column. 622 type ColumnFKConstraint struct { 623 Table TableName 624 Col Name // empty-string means use PK 625 Actions ReferenceActions 626 Match CompositeKeyMatchMethod 627 } 628 629 // ColumnComputedDef represents the description of a computed column. 630 type ColumnComputedDef struct { 631 Expr Expr 632 } 633 634 // ColumnFamilyConstraint represents FAMILY on a column. 635 type ColumnFamilyConstraint struct { 636 Family Name 637 Create bool 638 IfNotExists bool 639 } 640 641 // IndexTableDef represents an index definition within a CREATE TABLE 642 // statement. 643 type IndexTableDef struct { 644 Name Name 645 Columns IndexElemList 646 Sharded *ShardedIndexDef 647 Storing NameList 648 Interleave *InterleaveDef 649 Inverted bool 650 PartitionBy *PartitionBy 651 Predicate Expr 652 } 653 654 // Format implements the NodeFormatter interface. 655 func (node *IndexTableDef) Format(ctx *FmtCtx) { 656 if node.Inverted { 657 ctx.WriteString("INVERTED ") 658 } 659 ctx.WriteString("INDEX ") 660 if node.Name != "" { 661 ctx.FormatNode(&node.Name) 662 ctx.WriteByte(' ') 663 } 664 ctx.WriteByte('(') 665 ctx.FormatNode(&node.Columns) 666 ctx.WriteByte(')') 667 if node.Sharded != nil { 668 ctx.FormatNode(node.Sharded) 669 } 670 if node.Storing != nil { 671 ctx.WriteString(" STORING (") 672 ctx.FormatNode(&node.Storing) 673 ctx.WriteByte(')') 674 } 675 if node.Interleave != nil { 676 ctx.FormatNode(node.Interleave) 677 } 678 if node.PartitionBy != nil { 679 ctx.FormatNode(node.PartitionBy) 680 } 681 if node.Predicate != nil { 682 ctx.WriteString(" WHERE ") 683 ctx.FormatNode(node.Predicate) 684 } 685 } 686 687 // ConstraintTableDef represents a constraint definition within a CREATE TABLE 688 // statement. 689 type ConstraintTableDef interface { 690 TableDef 691 // Placeholder function to ensure that only desired types 692 // (*ConstraintTableDef) conform to the ConstraintTableDef interface. 693 constraintTableDef() 694 695 // SetName replaces the name of the definition in-place. Used in the parser. 696 SetName(name Name) 697 } 698 699 func (*UniqueConstraintTableDef) constraintTableDef() {} 700 func (*ForeignKeyConstraintTableDef) constraintTableDef() {} 701 func (*CheckConstraintTableDef) constraintTableDef() {} 702 703 // UniqueConstraintTableDef represents a unique constraint within a CREATE 704 // TABLE statement. 705 type UniqueConstraintTableDef struct { 706 IndexTableDef 707 PrimaryKey bool 708 } 709 710 // SetName implements the TableDef interface. 711 func (node *UniqueConstraintTableDef) SetName(name Name) { 712 node.Name = name 713 } 714 715 // Format implements the NodeFormatter interface. 716 func (node *UniqueConstraintTableDef) Format(ctx *FmtCtx) { 717 if node.Name != "" { 718 ctx.WriteString("CONSTRAINT ") 719 ctx.FormatNode(&node.Name) 720 ctx.WriteByte(' ') 721 } 722 if node.PrimaryKey { 723 ctx.WriteString("PRIMARY KEY ") 724 } else { 725 ctx.WriteString("UNIQUE ") 726 } 727 ctx.WriteByte('(') 728 ctx.FormatNode(&node.Columns) 729 ctx.WriteByte(')') 730 if node.Sharded != nil { 731 ctx.FormatNode(node.Sharded) 732 } 733 if node.Storing != nil { 734 ctx.WriteString(" STORING (") 735 ctx.FormatNode(&node.Storing) 736 ctx.WriteByte(')') 737 } 738 if node.Interleave != nil { 739 ctx.FormatNode(node.Interleave) 740 } 741 if node.PartitionBy != nil { 742 ctx.FormatNode(node.PartitionBy) 743 } 744 if node.Predicate != nil { 745 ctx.WriteString(" WHERE ") 746 ctx.FormatNode(node.Predicate) 747 } 748 } 749 750 // ReferenceAction is the method used to maintain referential integrity through 751 // foreign keys. 752 type ReferenceAction int 753 754 // The values for ReferenceAction. 755 const ( 756 NoAction ReferenceAction = iota 757 Restrict 758 SetNull 759 SetDefault 760 Cascade 761 ) 762 763 var referenceActionName = [...]string{ 764 NoAction: "NO ACTION", 765 Restrict: "RESTRICT", 766 SetNull: "SET NULL", 767 SetDefault: "SET DEFAULT", 768 Cascade: "CASCADE", 769 } 770 771 func (ra ReferenceAction) String() string { 772 return referenceActionName[ra] 773 } 774 775 // ReferenceActions contains the actions specified to maintain referential 776 // integrity through foreign keys for different operations. 777 type ReferenceActions struct { 778 Delete ReferenceAction 779 Update ReferenceAction 780 } 781 782 // Format implements the NodeFormatter interface. 783 func (node *ReferenceActions) Format(ctx *FmtCtx) { 784 if node.Delete != NoAction { 785 ctx.WriteString(" ON DELETE ") 786 ctx.WriteString(node.Delete.String()) 787 } 788 if node.Update != NoAction { 789 ctx.WriteString(" ON UPDATE ") 790 ctx.WriteString(node.Update.String()) 791 } 792 } 793 794 // CompositeKeyMatchMethod is the algorithm use when matching composite keys. 795 // See https://github.com/cockroachdb/cockroach/issues/20305 or 796 // https://www.postgresql.org/docs/11/sql-createtable.html for details on the 797 // different composite foreign key matching methods. 798 type CompositeKeyMatchMethod int 799 800 // The values for CompositeKeyMatchMethod. 801 const ( 802 MatchSimple CompositeKeyMatchMethod = iota 803 MatchFull 804 MatchPartial // Note: PARTIAL not actually supported at this point. 805 ) 806 807 var compositeKeyMatchMethodName = [...]string{ 808 MatchSimple: "MATCH SIMPLE", 809 MatchFull: "MATCH FULL", 810 MatchPartial: "MATCH PARTIAL", 811 } 812 813 func (c CompositeKeyMatchMethod) String() string { 814 return compositeKeyMatchMethodName[c] 815 } 816 817 // ForeignKeyConstraintTableDef represents a FOREIGN KEY constraint in the AST. 818 type ForeignKeyConstraintTableDef struct { 819 Name Name 820 Table TableName 821 FromCols NameList 822 ToCols NameList 823 Actions ReferenceActions 824 Match CompositeKeyMatchMethod 825 } 826 827 // Format implements the NodeFormatter interface. 828 func (node *ForeignKeyConstraintTableDef) Format(ctx *FmtCtx) { 829 if node.Name != "" { 830 ctx.WriteString("CONSTRAINT ") 831 ctx.FormatNode(&node.Name) 832 ctx.WriteByte(' ') 833 } 834 ctx.WriteString("FOREIGN KEY (") 835 ctx.FormatNode(&node.FromCols) 836 ctx.WriteString(") REFERENCES ") 837 ctx.FormatNode(&node.Table) 838 839 if len(node.ToCols) > 0 { 840 ctx.WriteByte(' ') 841 ctx.WriteByte('(') 842 ctx.FormatNode(&node.ToCols) 843 ctx.WriteByte(')') 844 } 845 846 if node.Match != MatchSimple { 847 ctx.WriteByte(' ') 848 ctx.WriteString(node.Match.String()) 849 } 850 851 ctx.FormatNode(&node.Actions) 852 } 853 854 // SetName implements the ConstraintTableDef interface. 855 func (node *ForeignKeyConstraintTableDef) SetName(name Name) { 856 node.Name = name 857 } 858 859 // CheckConstraintTableDef represents a check constraint within a CREATE 860 // TABLE statement. 861 type CheckConstraintTableDef struct { 862 Name Name 863 Expr Expr 864 Hidden bool 865 } 866 867 // SetName implements the ConstraintTableDef interface. 868 func (node *CheckConstraintTableDef) SetName(name Name) { 869 node.Name = name 870 } 871 872 // Format implements the NodeFormatter interface. 873 func (node *CheckConstraintTableDef) Format(ctx *FmtCtx) { 874 if node.Name != "" { 875 ctx.WriteString("CONSTRAINT ") 876 ctx.FormatNode(&node.Name) 877 ctx.WriteByte(' ') 878 } 879 ctx.WriteString("CHECK (") 880 ctx.FormatNode(node.Expr) 881 ctx.WriteByte(')') 882 } 883 884 // FamilyTableDef represents a family definition within a CREATE TABLE 885 // statement. 886 type FamilyTableDef struct { 887 Name Name 888 Columns NameList 889 } 890 891 // Format implements the NodeFormatter interface. 892 func (node *FamilyTableDef) Format(ctx *FmtCtx) { 893 ctx.WriteString("FAMILY ") 894 if node.Name != "" { 895 ctx.FormatNode(&node.Name) 896 ctx.WriteByte(' ') 897 } 898 ctx.WriteByte('(') 899 ctx.FormatNode(&node.Columns) 900 ctx.WriteByte(')') 901 } 902 903 // ShardedIndexDef represents a hash sharded secondary index definition within a CREATE 904 // TABLE or CREATE INDEX statement. 905 type ShardedIndexDef struct { 906 ShardBuckets Expr 907 } 908 909 // Format implements the NodeFormatter interface. 910 func (node *ShardedIndexDef) Format(ctx *FmtCtx) { 911 ctx.WriteString(" USING HASH WITH BUCKET_COUNT = ") 912 ctx.FormatNode(node.ShardBuckets) 913 } 914 915 // InterleaveDef represents an interleave definition within a CREATE TABLE 916 // or CREATE INDEX statement. 917 type InterleaveDef struct { 918 Parent TableName 919 Fields NameList 920 DropBehavior DropBehavior 921 } 922 923 // Format implements the NodeFormatter interface. 924 func (node *InterleaveDef) Format(ctx *FmtCtx) { 925 ctx.WriteString(" INTERLEAVE IN PARENT ") 926 ctx.FormatNode(&node.Parent) 927 ctx.WriteString(" (") 928 for i := range node.Fields { 929 if i > 0 { 930 ctx.WriteString(", ") 931 } 932 ctx.FormatNode(&node.Fields[i]) 933 } 934 ctx.WriteString(")") 935 if node.DropBehavior != DropDefault { 936 ctx.WriteString(" ") 937 ctx.WriteString(node.DropBehavior.String()) 938 } 939 } 940 941 // PartitionByType is an enum of each type of partitioning (LIST/RANGE). 942 type PartitionByType string 943 944 const ( 945 // PartitionByList indicates a PARTITION BY LIST clause. 946 PartitionByList PartitionByType = "LIST" 947 // PartitionByRange indicates a PARTITION BY LIST clause. 948 PartitionByRange PartitionByType = "RANGE" 949 ) 950 951 // PartitionBy represents an PARTITION BY definition within a CREATE/ALTER 952 // TABLE/INDEX statement. 953 type PartitionBy struct { 954 Fields NameList 955 // Exactly one of List or Range is required to be non-empty. 956 List []ListPartition 957 Range []RangePartition 958 } 959 960 // Format implements the NodeFormatter interface. 961 func (node *PartitionBy) Format(ctx *FmtCtx) { 962 if node == nil { 963 ctx.WriteString(` PARTITION BY NOTHING`) 964 return 965 } 966 if len(node.List) > 0 { 967 ctx.WriteString(` PARTITION BY LIST (`) 968 } else if len(node.Range) > 0 { 969 ctx.WriteString(` PARTITION BY RANGE (`) 970 } 971 ctx.FormatNode(&node.Fields) 972 ctx.WriteString(`) (`) 973 for i := range node.List { 974 if i > 0 { 975 ctx.WriteString(", ") 976 } 977 ctx.FormatNode(&node.List[i]) 978 } 979 for i := range node.Range { 980 if i > 0 { 981 ctx.WriteString(", ") 982 } 983 ctx.FormatNode(&node.Range[i]) 984 } 985 ctx.WriteString(`)`) 986 } 987 988 // ListPartition represents a PARTITION definition within a PARTITION BY LIST. 989 type ListPartition struct { 990 Name UnrestrictedName 991 Exprs Exprs 992 Subpartition *PartitionBy 993 } 994 995 // Format implements the NodeFormatter interface. 996 func (node *ListPartition) Format(ctx *FmtCtx) { 997 ctx.WriteString(`PARTITION `) 998 ctx.FormatNode(&node.Name) 999 ctx.WriteString(` VALUES IN (`) 1000 ctx.FormatNode(&node.Exprs) 1001 ctx.WriteByte(')') 1002 if node.Subpartition != nil { 1003 ctx.FormatNode(node.Subpartition) 1004 } 1005 } 1006 1007 // RangePartition represents a PARTITION definition within a PARTITION BY RANGE. 1008 type RangePartition struct { 1009 Name UnrestrictedName 1010 From Exprs 1011 To Exprs 1012 Subpartition *PartitionBy 1013 } 1014 1015 // Format implements the NodeFormatter interface. 1016 func (node *RangePartition) Format(ctx *FmtCtx) { 1017 ctx.WriteString(`PARTITION `) 1018 ctx.FormatNode(&node.Name) 1019 ctx.WriteString(` VALUES FROM (`) 1020 ctx.FormatNode(&node.From) 1021 ctx.WriteString(`) TO (`) 1022 ctx.FormatNode(&node.To) 1023 ctx.WriteByte(')') 1024 if node.Subpartition != nil { 1025 ctx.FormatNode(node.Subpartition) 1026 } 1027 } 1028 1029 // StorageParam is a key-value parameter for table storage. 1030 type StorageParam struct { 1031 Key Name 1032 Value Expr 1033 } 1034 1035 // StorageParams is a list of StorageParams. 1036 type StorageParams []StorageParam 1037 1038 // Format implements the NodeFormatter interface. 1039 func (o *StorageParams) Format(ctx *FmtCtx) { 1040 for i := range *o { 1041 n := &(*o)[i] 1042 if i > 0 { 1043 ctx.WriteString(", ") 1044 } 1045 ctx.FormatNode(&n.Key) 1046 if n.Value != nil { 1047 ctx.WriteString(` = `) 1048 ctx.FormatNode(n.Value) 1049 } 1050 } 1051 } 1052 1053 // CreateTableOnCommitSetting represents the CREATE TABLE ... ON COMMIT <action> 1054 // parameters. 1055 type CreateTableOnCommitSetting uint32 1056 1057 const ( 1058 // CreateTableOnCommitUnset indicates that ON COMMIT was unset. 1059 CreateTableOnCommitUnset CreateTableOnCommitSetting = iota 1060 // CreateTableOnCommitPreserveRows indicates that ON COMMIT PRESERVE ROWS was set. 1061 CreateTableOnCommitPreserveRows 1062 ) 1063 1064 // CreateTable represents a CREATE TABLE statement. 1065 type CreateTable struct { 1066 IfNotExists bool 1067 Table TableName 1068 Interleave *InterleaveDef 1069 PartitionBy *PartitionBy 1070 Temporary bool 1071 StorageParams StorageParams 1072 OnCommit CreateTableOnCommitSetting 1073 // In CREATE...AS queries, Defs represents a list of ColumnTableDefs, one for 1074 // each column, and a ConstraintTableDef for each constraint on a subset of 1075 // these columns. 1076 Defs TableDefs 1077 AsSource *Select 1078 } 1079 1080 // As returns true if this table represents a CREATE TABLE ... AS statement, 1081 // false otherwise. 1082 func (node *CreateTable) As() bool { 1083 return node.AsSource != nil 1084 } 1085 1086 // AsHasUserSpecifiedPrimaryKey returns true if a CREATE TABLE ... AS statement 1087 // has a PRIMARY KEY constraint specified. 1088 func (node *CreateTable) AsHasUserSpecifiedPrimaryKey() bool { 1089 if node.As() { 1090 for _, def := range node.Defs { 1091 if d, ok := def.(*ColumnTableDef); !ok { 1092 return false 1093 } else if d.PrimaryKey.IsPrimaryKey { 1094 return true 1095 } 1096 } 1097 } 1098 return false 1099 } 1100 1101 // Format implements the NodeFormatter interface. 1102 func (node *CreateTable) Format(ctx *FmtCtx) { 1103 ctx.WriteString("CREATE ") 1104 if node.Temporary { 1105 ctx.WriteString("TEMPORARY ") 1106 } 1107 ctx.WriteString("TABLE ") 1108 if node.IfNotExists { 1109 ctx.WriteString("IF NOT EXISTS ") 1110 } 1111 ctx.FormatNode(&node.Table) 1112 node.FormatBody(ctx) 1113 } 1114 1115 // FormatBody formats the "body" of the create table definition - everything 1116 // but the CREATE TABLE tableName part. 1117 func (node *CreateTable) FormatBody(ctx *FmtCtx) { 1118 if node.As() { 1119 if len(node.Defs) > 0 { 1120 ctx.WriteString(" (") 1121 ctx.FormatNode(&node.Defs) 1122 ctx.WriteByte(')') 1123 } 1124 ctx.WriteString(" AS ") 1125 ctx.FormatNode(node.AsSource) 1126 } else { 1127 ctx.WriteString(" (") 1128 ctx.FormatNode(&node.Defs) 1129 ctx.WriteByte(')') 1130 if node.Interleave != nil { 1131 ctx.FormatNode(node.Interleave) 1132 } 1133 if node.PartitionBy != nil { 1134 ctx.FormatNode(node.PartitionBy) 1135 } 1136 // No storage parameters are implemented, so we never list the storage 1137 // parameters in the output format. 1138 } 1139 } 1140 1141 // HoistConstraints finds column check and foreign key constraints defined 1142 // inline with their columns and makes them table-level constraints, stored in 1143 // n.Defs. For example, the foreign key constraint in 1144 // 1145 // CREATE TABLE foo (a INT REFERENCES bar(a)) 1146 // 1147 // gets pulled into a top-level constraint like: 1148 // 1149 // CREATE TABLE foo (a INT, FOREIGN KEY (a) REFERENCES bar(a)) 1150 // 1151 // Similarly, the CHECK constraint in 1152 // 1153 // CREATE TABLE foo (a INT CHECK (a < 1), b INT) 1154 // 1155 // gets pulled into a top-level constraint like: 1156 // 1157 // CREATE TABLE foo (a INT, b INT, CHECK (a < 1)) 1158 // 1159 // Note that some SQL databases require that a constraint attached to a column 1160 // to refer only to the column it is attached to. We follow Postgres' behavior, 1161 // however, in omitting this restriction by blindly hoisting all column 1162 // constraints. For example, the following table definition is accepted in 1163 // CockroachDB and Postgres, but not necessarily other SQL databases: 1164 // 1165 // CREATE TABLE foo (a INT CHECK (a < b), b INT) 1166 // 1167 // Unique constraints are not hoisted. 1168 // 1169 func (node *CreateTable) HoistConstraints() { 1170 for _, d := range node.Defs { 1171 if col, ok := d.(*ColumnTableDef); ok { 1172 for _, checkExpr := range col.CheckExprs { 1173 node.Defs = append(node.Defs, 1174 &CheckConstraintTableDef{ 1175 Expr: checkExpr.Expr, 1176 Name: checkExpr.ConstraintName, 1177 }, 1178 ) 1179 } 1180 col.CheckExprs = nil 1181 if col.HasFKConstraint() { 1182 var targetCol NameList 1183 if col.References.Col != "" { 1184 targetCol = append(targetCol, col.References.Col) 1185 } 1186 node.Defs = append(node.Defs, &ForeignKeyConstraintTableDef{ 1187 Table: *col.References.Table, 1188 FromCols: NameList{col.Name}, 1189 ToCols: targetCol, 1190 Name: col.References.ConstraintName, 1191 Actions: col.References.Actions, 1192 Match: col.References.Match, 1193 }) 1194 col.References.Table = nil 1195 } 1196 } 1197 } 1198 } 1199 1200 // CreateSchema represents a CREATE SCHEMA statement. 1201 type CreateSchema struct { 1202 IfNotExists bool 1203 Schema string 1204 } 1205 1206 // Format implements the NodeFormatter interface. 1207 func (node *CreateSchema) Format(ctx *FmtCtx) { 1208 ctx.WriteString("CREATE SCHEMA ") 1209 1210 if node.IfNotExists { 1211 ctx.WriteString("IF NOT EXISTS ") 1212 } 1213 1214 ctx.WriteString(node.Schema) 1215 } 1216 1217 // CreateSequence represents a CREATE SEQUENCE statement. 1218 type CreateSequence struct { 1219 IfNotExists bool 1220 Name TableName 1221 Temporary bool 1222 Options SequenceOptions 1223 } 1224 1225 // Format implements the NodeFormatter interface. 1226 func (node *CreateSequence) Format(ctx *FmtCtx) { 1227 ctx.WriteString("CREATE ") 1228 1229 if node.Temporary { 1230 ctx.WriteString("TEMPORARY ") 1231 } 1232 1233 ctx.WriteString("SEQUENCE ") 1234 1235 if node.IfNotExists { 1236 ctx.WriteString("IF NOT EXISTS ") 1237 } 1238 ctx.FormatNode(&node.Name) 1239 ctx.FormatNode(&node.Options) 1240 } 1241 1242 // SequenceOptions represents a list of sequence options. 1243 type SequenceOptions []SequenceOption 1244 1245 // Format implements the NodeFormatter interface. 1246 func (node *SequenceOptions) Format(ctx *FmtCtx) { 1247 for i := range *node { 1248 option := &(*node)[i] 1249 ctx.WriteByte(' ') 1250 switch option.Name { 1251 case SeqOptCycle, SeqOptNoCycle: 1252 ctx.WriteString(option.Name) 1253 case SeqOptCache: 1254 ctx.WriteString(option.Name) 1255 ctx.WriteByte(' ') 1256 ctx.Printf("%d", *option.IntVal) 1257 case SeqOptMaxValue, SeqOptMinValue: 1258 if option.IntVal == nil { 1259 ctx.WriteString("NO ") 1260 ctx.WriteString(option.Name) 1261 } else { 1262 ctx.WriteString(option.Name) 1263 ctx.WriteByte(' ') 1264 ctx.Printf("%d", *option.IntVal) 1265 } 1266 case SeqOptStart: 1267 ctx.WriteString(option.Name) 1268 ctx.WriteByte(' ') 1269 if option.OptionalWord { 1270 ctx.WriteString("WITH ") 1271 } 1272 ctx.Printf("%d", *option.IntVal) 1273 case SeqOptIncrement: 1274 ctx.WriteString(option.Name) 1275 ctx.WriteByte(' ') 1276 if option.OptionalWord { 1277 ctx.WriteString("BY ") 1278 } 1279 ctx.Printf("%d", *option.IntVal) 1280 case SeqOptVirtual: 1281 ctx.WriteString(option.Name) 1282 case SeqOptOwnedBy: 1283 ctx.WriteString(option.Name) 1284 ctx.WriteByte(' ') 1285 switch option.ColumnItemVal { 1286 case nil: 1287 ctx.WriteString("NONE") 1288 default: 1289 ctx.FormatNode(option.ColumnItemVal) 1290 } 1291 default: 1292 panic(errors.AssertionFailedf("unexpected SequenceOption: %v", option)) 1293 } 1294 } 1295 } 1296 1297 // SequenceOption represents an option on a CREATE SEQUENCE statement. 1298 type SequenceOption struct { 1299 Name string 1300 1301 IntVal *int64 1302 1303 OptionalWord bool 1304 1305 ColumnItemVal *ColumnItem 1306 } 1307 1308 // Names of options on CREATE SEQUENCE. 1309 const ( 1310 SeqOptAs = "AS" 1311 SeqOptCycle = "CYCLE" 1312 SeqOptNoCycle = "NO CYCLE" 1313 SeqOptOwnedBy = "OWNED BY" 1314 SeqOptCache = "CACHE" 1315 SeqOptIncrement = "INCREMENT" 1316 SeqOptMinValue = "MINVALUE" 1317 SeqOptMaxValue = "MAXVALUE" 1318 SeqOptStart = "START" 1319 SeqOptVirtual = "VIRTUAL" 1320 1321 // Avoid unused warning for constants. 1322 _ = SeqOptAs 1323 ) 1324 1325 // LikeTableDef represents a LIKE table declaration on a CREATE TABLE statement. 1326 type LikeTableDef struct { 1327 Name TableName 1328 Options []LikeTableOption 1329 } 1330 1331 // LikeTableOption represents an individual INCLUDING / EXCLUDING statement 1332 // on a LIKE table declaration. 1333 type LikeTableOption struct { 1334 Excluded bool 1335 Opt LikeTableOpt 1336 } 1337 1338 // Format implements the NodeFormatter interface. 1339 func (def *LikeTableDef) Format(ctx *FmtCtx) { 1340 ctx.WriteString("LIKE ") 1341 ctx.FormatNode(&def.Name) 1342 for _, o := range def.Options { 1343 ctx.WriteString(" ") 1344 ctx.FormatNode(o) 1345 } 1346 } 1347 1348 // Format implements the NodeFormatter interface. 1349 func (l LikeTableOption) Format(ctx *FmtCtx) { 1350 if l.Excluded { 1351 ctx.WriteString("EXCLUDING ") 1352 } else { 1353 ctx.WriteString("INCLUDING ") 1354 } 1355 ctx.WriteString(l.Opt.String()) 1356 } 1357 1358 // LikeTableOpt represents one of the types of things that can be included or 1359 // excluded in a LIKE table declaration. It's a bitmap, where each of the Opt 1360 // values is a single enabled bit in the map. 1361 type LikeTableOpt int 1362 1363 // The values for LikeTableOpt. 1364 const ( 1365 LikeTableOptConstraints LikeTableOpt = 1 << iota 1366 LikeTableOptDefaults 1367 LikeTableOptGenerated 1368 LikeTableOptIndexes 1369 1370 // Make sure this field stays last! 1371 likeTableOptInvalid 1372 ) 1373 1374 // LikeTableOptAll is the full LikeTableOpt bitmap. 1375 const LikeTableOptAll = ^likeTableOptInvalid 1376 1377 // Has returns true if the receiver has the other options bits set. 1378 func (o LikeTableOpt) Has(other LikeTableOpt) bool { 1379 return int(o)&int(other) != 0 1380 } 1381 1382 func (o LikeTableOpt) String() string { 1383 switch o { 1384 case LikeTableOptConstraints: 1385 return "CONSTRAINTS" 1386 case LikeTableOptDefaults: 1387 return "DEFAULTS" 1388 case LikeTableOptGenerated: 1389 return "GENERATED" 1390 case LikeTableOptIndexes: 1391 return "INDEXES" 1392 case LikeTableOptAll: 1393 return "ALL" 1394 default: 1395 panic("unknown like table opt" + strconv.Itoa(int(o))) 1396 } 1397 } 1398 1399 // ToRoleOptions converts KVOptions to a roleoption.List using 1400 // typeAsString to convert exprs to strings. 1401 func (o KVOptions) ToRoleOptions( 1402 typeAsStringOrNull func(e Expr, op string) (func() (bool, string, error), error), op string, 1403 ) (roleoption.List, error) { 1404 roleOptions := make(roleoption.List, len(o)) 1405 1406 for i, ro := range o { 1407 option, err := roleoption.ToOption(ro.Key.String()) 1408 if err != nil { 1409 return nil, err 1410 } 1411 1412 if ro.Value != nil { 1413 if ro.Value == DNull { 1414 roleOptions[i] = roleoption.RoleOption{ 1415 Option: option, HasValue: true, Value: func() (bool, string, error) { 1416 return true, "", nil 1417 }, 1418 } 1419 } else { 1420 strFn, err := typeAsStringOrNull(ro.Value, op) 1421 if err != nil { 1422 return nil, err 1423 } 1424 1425 if err != nil { 1426 return nil, err 1427 } 1428 roleOptions[i] = roleoption.RoleOption{ 1429 Option: option, Value: strFn, HasValue: true, 1430 } 1431 } 1432 } else { 1433 roleOptions[i] = roleoption.RoleOption{ 1434 Option: option, HasValue: false, 1435 } 1436 } 1437 } 1438 1439 return roleOptions, nil 1440 } 1441 1442 func (o *KVOptions) formatAsRoleOptions(ctx *FmtCtx) { 1443 for _, option := range *o { 1444 ctx.WriteString(" ") 1445 ctx.WriteString( 1446 // "_" replaces space (" ") in YACC for handling tree.Name formatting. 1447 strings.ReplaceAll( 1448 strings.ToUpper(option.Key.String()), "_", " "), 1449 ) 1450 1451 // Password is a special case. 1452 if strings.ToUpper(option.Key.String()) == "PASSWORD" { 1453 ctx.WriteString(" ") 1454 if ctx.flags.HasFlags(FmtShowPasswords) { 1455 ctx.FormatNode(option.Value) 1456 } else { 1457 ctx.WriteString("*****") 1458 } 1459 } else if option.Value == DNull { 1460 ctx.WriteString(" ") 1461 ctx.FormatNode(option.Value) 1462 } else if option.Value != nil { 1463 ctx.WriteString(" ") 1464 ctx.FormatNode(option.Value) 1465 } 1466 } 1467 } 1468 1469 // CreateRole represents a CREATE ROLE statement. 1470 type CreateRole struct { 1471 Name Expr 1472 IfNotExists bool 1473 IsRole bool 1474 KVOptions KVOptions 1475 } 1476 1477 // Format implements the NodeFormatter interface. 1478 func (node *CreateRole) Format(ctx *FmtCtx) { 1479 ctx.WriteString("CREATE") 1480 if node.IsRole { 1481 ctx.WriteString(" ROLE ") 1482 } else { 1483 ctx.WriteString(" USER ") 1484 } 1485 if node.IfNotExists { 1486 ctx.WriteString("IF NOT EXISTS ") 1487 } 1488 ctx.FormatNode(node.Name) 1489 1490 if len(node.KVOptions) > 0 { 1491 ctx.WriteString(" WITH") 1492 node.KVOptions.formatAsRoleOptions(ctx) 1493 } 1494 } 1495 1496 // AlterRole represents an ALTER ROLE statement. 1497 type AlterRole struct { 1498 Name Expr 1499 IfExists bool 1500 IsRole bool 1501 KVOptions KVOptions 1502 } 1503 1504 // Format implements the NodeFormatter interface. 1505 func (node *AlterRole) Format(ctx *FmtCtx) { 1506 ctx.WriteString("ALTER") 1507 if node.IsRole { 1508 ctx.WriteString(" ROLE ") 1509 } else { 1510 ctx.WriteString(" USER ") 1511 } 1512 if node.IfExists { 1513 ctx.WriteString("IF EXISTS ") 1514 } 1515 ctx.FormatNode(node.Name) 1516 1517 if len(node.KVOptions) > 0 { 1518 ctx.WriteString(" WITH") 1519 node.KVOptions.formatAsRoleOptions(ctx) 1520 } 1521 } 1522 1523 // CreateView represents a CREATE VIEW statement. 1524 type CreateView struct { 1525 Name TableName 1526 ColumnNames NameList 1527 AsSource *Select 1528 IfNotExists bool 1529 Temporary bool 1530 Replace bool 1531 } 1532 1533 // Format implements the NodeFormatter interface. 1534 func (node *CreateView) Format(ctx *FmtCtx) { 1535 ctx.WriteString("CREATE ") 1536 1537 if node.Replace { 1538 ctx.WriteString("OR REPLACE ") 1539 } 1540 1541 if node.Temporary { 1542 ctx.WriteString("TEMPORARY ") 1543 } 1544 1545 ctx.WriteString("VIEW ") 1546 1547 if node.IfNotExists { 1548 ctx.WriteString("IF NOT EXISTS ") 1549 } 1550 ctx.FormatNode(&node.Name) 1551 1552 if len(node.ColumnNames) > 0 { 1553 ctx.WriteByte(' ') 1554 ctx.WriteByte('(') 1555 ctx.FormatNode(&node.ColumnNames) 1556 ctx.WriteByte(')') 1557 } 1558 1559 ctx.WriteString(" AS ") 1560 ctx.FormatNode(node.AsSource) 1561 } 1562 1563 // CreateStats represents a CREATE STATISTICS statement. 1564 type CreateStats struct { 1565 Name Name 1566 ColumnNames NameList 1567 Table TableExpr 1568 Options CreateStatsOptions 1569 } 1570 1571 // Format implements the NodeFormatter interface. 1572 func (node *CreateStats) Format(ctx *FmtCtx) { 1573 ctx.WriteString("CREATE STATISTICS ") 1574 ctx.FormatNode(&node.Name) 1575 1576 if len(node.ColumnNames) > 0 { 1577 ctx.WriteString(" ON ") 1578 ctx.FormatNode(&node.ColumnNames) 1579 } 1580 1581 ctx.WriteString(" FROM ") 1582 ctx.FormatNode(node.Table) 1583 1584 if !node.Options.Empty() { 1585 ctx.WriteString(" WITH OPTIONS ") 1586 ctx.FormatNode(&node.Options) 1587 } 1588 } 1589 1590 // CreateStatsOptions contains options for CREATE STATISTICS. 1591 type CreateStatsOptions struct { 1592 // Throttling enables throttling and indicates the fraction of time we are 1593 // idling (between 0 and 1). 1594 Throttling float64 1595 1596 // AsOf performs a historical read at the given timestamp. 1597 // Note that the timestamp will be moved up during the operation if it gets 1598 // too old (in order to avoid problems with TTL expiration). 1599 AsOf AsOfClause 1600 } 1601 1602 // Empty returns true if no options were provided. 1603 func (o *CreateStatsOptions) Empty() bool { 1604 return o.Throttling == 0 && o.AsOf.Expr == nil 1605 } 1606 1607 // Format implements the NodeFormatter interface. 1608 func (o *CreateStatsOptions) Format(ctx *FmtCtx) { 1609 sep := "" 1610 if o.Throttling != 0 { 1611 fmt.Fprintf(ctx, "THROTTLING %g", o.Throttling) 1612 sep = " " 1613 } 1614 if o.AsOf.Expr != nil { 1615 ctx.WriteString(sep) 1616 ctx.FormatNode(&o.AsOf) 1617 sep = " " 1618 } 1619 } 1620 1621 // CombineWith combines two options, erroring out if the two options contain 1622 // incompatible settings. 1623 func (o *CreateStatsOptions) CombineWith(other *CreateStatsOptions) error { 1624 if other.Throttling != 0 { 1625 if o.Throttling != 0 { 1626 return errors.New("THROTTLING specified multiple times") 1627 } 1628 o.Throttling = other.Throttling 1629 } 1630 if other.AsOf.Expr != nil { 1631 if o.AsOf.Expr != nil { 1632 return errors.New("AS OF specified multiple times") 1633 } 1634 o.AsOf = other.AsOf 1635 } 1636 return nil 1637 }