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

     1  // Copyright 2022 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tree
    12  
    13  // ReplicationCutoverTime represent the user-specified cutover time
    14  type ReplicationCutoverTime struct {
    15  	Timestamp Expr
    16  	Latest    bool
    17  }
    18  
    19  // AlterTenantReplication represents an ALTER VIRTUAL CLUSTER REPLICATION statement.
    20  type AlterTenantReplication struct {
    21  	TenantSpec *TenantSpec
    22  	Command    JobCommand
    23  	Cutover    *ReplicationCutoverTime
    24  	Options    TenantReplicationOptions
    25  }
    26  
    27  var _ Statement = &AlterTenantReplication{}
    28  
    29  // Format implements the NodeFormatter interface.
    30  func (n *AlterTenantReplication) Format(ctx *FmtCtx) {
    31  	ctx.WriteString("ALTER VIRTUAL CLUSTER ")
    32  	ctx.FormatNode(n.TenantSpec)
    33  	ctx.WriteByte(' ')
    34  	if n.Cutover != nil {
    35  		ctx.WriteString("COMPLETE REPLICATION TO ")
    36  		if n.Cutover.Latest {
    37  			ctx.WriteString("LATEST")
    38  		} else {
    39  			ctx.WriteString("SYSTEM TIME ")
    40  			ctx.FormatNode(n.Cutover.Timestamp)
    41  		}
    42  	} else if !n.Options.IsDefault() {
    43  		ctx.WriteString("SET REPLICATION ")
    44  		ctx.FormatNode(&n.Options)
    45  	} else if n.Command == PauseJob || n.Command == ResumeJob {
    46  		ctx.WriteString(JobCommandToStatement[n.Command])
    47  		ctx.WriteString(" REPLICATION")
    48  	}
    49  }
    50  
    51  // TenantCapability is a key-value parameter representing a tenant capability.
    52  type TenantCapability struct {
    53  	Name  string
    54  	Value Expr
    55  }
    56  
    57  // AlterTenantCapability represents an ALTER VIRTUAL CLUSTER CAPABILITY statement.
    58  type AlterTenantCapability struct {
    59  	TenantSpec   *TenantSpec
    60  	Capabilities []TenantCapability
    61  	IsRevoke     bool
    62  
    63  	AllCapabilities bool
    64  }
    65  
    66  var _ Statement = &AlterTenantCapability{}
    67  
    68  // Format implements the NodeFormatter interface.
    69  func (n *AlterTenantCapability) Format(ctx *FmtCtx) {
    70  	ctx.WriteString("ALTER VIRTUAL CLUSTER ")
    71  	ctx.FormatNode(n.TenantSpec)
    72  	if n.IsRevoke {
    73  		ctx.WriteString(" REVOKE ")
    74  	} else {
    75  		ctx.WriteString(" GRANT ")
    76  	}
    77  	if n.AllCapabilities {
    78  		ctx.WriteString("ALL CAPABILITIES")
    79  	} else {
    80  		ctx.WriteString("CAPABILITY ")
    81  		for i, capability := range n.Capabilities {
    82  			if i > 0 {
    83  				ctx.WriteString(", ")
    84  			}
    85  			ctx.WriteString(capability.Name)
    86  			value := capability.Value
    87  			if value != nil {
    88  				ctx.WriteString(" = ")
    89  				ctx.FormatNode(value)
    90  			}
    91  		}
    92  	}
    93  }
    94  
    95  // TenantSpec designates a tenant for the ALTER VIRTUAL CLUSTER statements.
    96  type TenantSpec struct {
    97  	Expr   Expr
    98  	IsName bool
    99  	All    bool
   100  }
   101  
   102  // alreadyDelimitedAsSyntacticDExpr is an interface that marks
   103  // Expr types for which there is never an ambiguity when
   104  // the expression syntax is followed by a non-reserved
   105  // keyword. When this property is true, that expression
   106  // can be pretty-printed without enclosing parentheses in
   107  // a context followed by more non-reserved keywords, and
   108  // result in syntax that is still unambiguous.
   109  // That is, given an expression E and an arbitrary following
   110  // word X, the syntax "E X" is always unambiguously parsed
   111  // as "(E) X".
   112  //
   113  // This property is obviously true of "atomic" expressions such as
   114  // string and number literals, and also obviously true of
   115  // well-enclosed expressions "(...)" / "[...]". However, it is not
   116  // always true of other composite expression types. For example,
   117  // "A::B" (CastExpr) is not well-delimited because there are
   118  // identifiers/keywords such that "A::B C" can be parsed as "A::(B
   119  // C)". Consider "'a'::INTERVAL" and the non-reserved keyword
   120  // "MINUTE".
   121  //
   122  // This property is closely related to the d_expr syntactic rule in
   123  // the grammar, hence its name. *Approximately* the expression types
   124  // produced by the d_expr rule tend to exhibit the "well-delimited"
   125  // property. However, this is not a proper equivalence: certain Expr
   126  // types are _also_ produced by other parsing rules than d_expr, so
   127  // inspection of the contents of the Expr object is necessary to
   128  // determine whether it is well-delimited or not (for example, some
   129  // FuncExpr objects are well-delimited, and others are not).
   130  // Therefore, it is not generally correct to assign the property to
   131  // all the d_expr expression *types*. We can only do so for a few
   132  // types for which we know that *all possible objects* of that type
   133  // are well-delimited, such as Subquery, NumVal or Placeholder.
   134  type alreadyDelimitedAsSyntacticDExpr interface {
   135  	Expr
   136  	alreadyDelimitedAsSyntacticDExpr()
   137  }
   138  
   139  func (*UnresolvedName) alreadyDelimitedAsSyntacticDExpr() {}
   140  func (*ParenExpr) alreadyDelimitedAsSyntacticDExpr()      {}
   141  func (*Subquery) alreadyDelimitedAsSyntacticDExpr()       {}
   142  func (*Placeholder) alreadyDelimitedAsSyntacticDExpr()    {}
   143  func (*NumVal) alreadyDelimitedAsSyntacticDExpr()         {}
   144  func (*StrVal) alreadyDelimitedAsSyntacticDExpr()         {}
   145  func (dNull) alreadyDelimitedAsSyntacticDExpr()           {}
   146  
   147  // Format implements the NodeFormatter interface.
   148  func (n *TenantSpec) Format(ctx *FmtCtx) {
   149  	if n.All {
   150  		ctx.WriteString("ALL")
   151  	} else if n.IsName {
   152  		// Beware to enclose the expression within parentheses if it is
   153  		// not a simple identifier and is not already enclosed in
   154  		// parentheses.
   155  		_, canOmitParentheses := n.Expr.(alreadyDelimitedAsSyntacticDExpr)
   156  		if !canOmitParentheses {
   157  			ctx.WriteByte('(')
   158  		}
   159  		ctx.FormatNode(n.Expr)
   160  		if !canOmitParentheses {
   161  			ctx.WriteByte(')')
   162  		}
   163  	} else {
   164  		ctx.WriteByte('[')
   165  		ctx.FormatNode(n.Expr)
   166  		ctx.WriteByte(']')
   167  	}
   168  }
   169  
   170  // AlterTenantRename represents an ALTER VIRTUAL CLUSTER RENAME statement.
   171  type AlterTenantRename struct {
   172  	TenantSpec *TenantSpec
   173  
   174  	// For NewName we only support the name syntax, not the numeric
   175  	// syntax. So we could make-do with just an Expr here. However, we
   176  	// like to use TenantSpec as a container for that name because it
   177  	// takes care of pretty-printing with all the special rules. See the
   178  	// doc of (*TenantSpec).Format() for details.
   179  	NewName *TenantSpec
   180  }
   181  
   182  var _ Statement = &AlterTenantRename{}
   183  
   184  // Format implements the NodeFormatter interface.
   185  func (n *AlterTenantRename) Format(ctx *FmtCtx) {
   186  	ctx.WriteString("ALTER VIRTUAL CLUSTER ")
   187  	ctx.FormatNode(n.TenantSpec)
   188  	ctx.WriteString(" RENAME TO ")
   189  	ctx.FormatNode(n.NewName)
   190  }
   191  
   192  // AlterTenantService represents an ALTER VIRTUAL CLUSTER START/STOP SERVICE statement.
   193  type AlterTenantService struct {
   194  	TenantSpec *TenantSpec
   195  	Command    TenantServiceCmd
   196  }
   197  
   198  // TenantServiceCmd represents a parameter to ALTER VIRTUAL CLUSTER.
   199  type TenantServiceCmd int8
   200  
   201  const (
   202  	// TenantStartServiceExternal encodes START SERVICE EXTERNAL.
   203  	TenantStartServiceExternal TenantServiceCmd = 0
   204  	// TenantStartServiceExternal encodes START SERVICE SHARED.
   205  	TenantStartServiceShared TenantServiceCmd = 1
   206  	// TenantStartServiceExternal encodes STOP SERVICE.
   207  	TenantStopService TenantServiceCmd = 2
   208  )
   209  
   210  var _ Statement = &AlterTenantService{}
   211  
   212  // Format implements the NodeFormatter interface.
   213  func (n *AlterTenantService) Format(ctx *FmtCtx) {
   214  	ctx.WriteString("ALTER VIRTUAL CLUSTER ")
   215  	ctx.FormatNode(n.TenantSpec)
   216  	switch n.Command {
   217  	case TenantStartServiceExternal:
   218  		ctx.WriteString(" START SERVICE EXTERNAL")
   219  	case TenantStartServiceShared:
   220  		ctx.WriteString(" START SERVICE SHARED")
   221  	case TenantStopService:
   222  		ctx.WriteString(" STOP SERVICE")
   223  	}
   224  }