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  }