github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/txn.go (about)

     1  // Copyright 2015 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tree
    12  
    13  import (
    14  	"fmt"
    15  	"strings"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    19  )
    20  
    21  // IsolationLevel holds the isolation level for a transaction.
    22  type IsolationLevel int
    23  
    24  // IsolationLevel values
    25  const (
    26  	UnspecifiedIsolation IsolationLevel = iota
    27  	SerializableIsolation
    28  )
    29  
    30  var isolationLevelNames = [...]string{
    31  	UnspecifiedIsolation:  "UNSPECIFIED",
    32  	SerializableIsolation: "SERIALIZABLE",
    33  }
    34  
    35  // IsolationLevelMap is a map from string isolation level name to isolation
    36  // level, in the lowercase format that set isolation_level supports.
    37  var IsolationLevelMap = map[string]IsolationLevel{
    38  	"serializable": SerializableIsolation,
    39  }
    40  
    41  func (i IsolationLevel) String() string {
    42  	if i < 0 || i > IsolationLevel(len(isolationLevelNames)-1) {
    43  		return fmt.Sprintf("IsolationLevel(%d)", i)
    44  	}
    45  	return isolationLevelNames[i]
    46  }
    47  
    48  // UserPriority holds the user priority for a transaction.
    49  type UserPriority int
    50  
    51  // UserPriority values
    52  const (
    53  	UnspecifiedUserPriority UserPriority = iota
    54  	Low
    55  	Normal
    56  	High
    57  )
    58  
    59  var userPriorityNames = [...]string{
    60  	UnspecifiedUserPriority: "UNSPECIFIED",
    61  	Low:                     "LOW",
    62  	Normal:                  "NORMAL",
    63  	High:                    "HIGH",
    64  }
    65  
    66  func (up UserPriority) String() string {
    67  	if up < 0 || up > UserPriority(len(userPriorityNames)-1) {
    68  		return fmt.Sprintf("UserPriority(%d)", up)
    69  	}
    70  	return userPriorityNames[up]
    71  }
    72  
    73  // UserPriorityFromString converts a string into a UserPriority.
    74  func UserPriorityFromString(val string) (_ UserPriority, ok bool) {
    75  	switch strings.ToUpper(val) {
    76  	case "LOW":
    77  		return Low, true
    78  	case "NORMAL":
    79  		return Normal, true
    80  	case "HIGH":
    81  		return High, true
    82  	default:
    83  		return 0, false
    84  	}
    85  }
    86  
    87  // ReadWriteMode holds the read write mode for a transaction.
    88  type ReadWriteMode int
    89  
    90  // ReadWriteMode values
    91  const (
    92  	UnspecifiedReadWriteMode ReadWriteMode = iota
    93  	ReadOnly
    94  	ReadWrite
    95  )
    96  
    97  var readWriteModeNames = [...]string{
    98  	UnspecifiedReadWriteMode: "UNSPECIFIED",
    99  	ReadOnly:                 "ONLY",
   100  	ReadWrite:                "WRITE",
   101  }
   102  
   103  func (ro ReadWriteMode) String() string {
   104  	if ro < 0 || ro > ReadWriteMode(len(readWriteModeNames)-1) {
   105  		return fmt.Sprintf("ReadWriteMode(%d)", ro)
   106  	}
   107  	return readWriteModeNames[ro]
   108  }
   109  
   110  // TransactionModes holds the transaction modes for a transaction.
   111  type TransactionModes struct {
   112  	Isolation     IsolationLevel
   113  	UserPriority  UserPriority
   114  	ReadWriteMode ReadWriteMode
   115  	AsOf          AsOfClause
   116  }
   117  
   118  // Format implements the NodeFormatter interface.
   119  func (node *TransactionModes) Format(ctx *FmtCtx) {
   120  	var sep string
   121  	if node.Isolation != UnspecifiedIsolation {
   122  		ctx.Printf(" ISOLATION LEVEL %s", node.Isolation)
   123  		sep = ","
   124  	}
   125  	if node.UserPriority != UnspecifiedUserPriority {
   126  		ctx.Printf("%s PRIORITY %s", sep, node.UserPriority)
   127  		sep = ","
   128  	}
   129  	if node.ReadWriteMode != UnspecifiedReadWriteMode {
   130  		ctx.Printf("%s READ %s", sep, node.ReadWriteMode)
   131  	}
   132  	if node.AsOf.Expr != nil {
   133  		ctx.WriteString(sep)
   134  		ctx.WriteString(" ")
   135  		node.AsOf.Format(ctx)
   136  	}
   137  }
   138  
   139  var (
   140  	errIsolationLevelSpecifiedMultipleTimes = pgerror.New(pgcode.Syntax, "isolation level specified multiple times")
   141  	errUserPrioritySpecifiedMultipleTimes   = pgerror.New(pgcode.Syntax, "user priority specified multiple times")
   142  	errReadModeSpecifiedMultipleTimes       = pgerror.New(pgcode.Syntax, "read mode specified multiple times")
   143  	errAsOfSpecifiedMultipleTimes           = pgerror.New(pgcode.Syntax, "AS OF SYSTEM TIME specified multiple times")
   144  
   145  	// ErrAsOfSpecifiedWithReadWrite is returned when a statement attempts to set
   146  	// a historical query to READ WRITE which conflicts with its implied READ ONLY
   147  	// mode.
   148  	ErrAsOfSpecifiedWithReadWrite = pgerror.New(pgcode.Syntax, "AS OF SYSTEM TIME specified with READ WRITE mode")
   149  )
   150  
   151  // Merge groups two sets of transaction modes together.
   152  // Used in the parser.
   153  func (node *TransactionModes) Merge(other TransactionModes) error {
   154  	if other.Isolation != UnspecifiedIsolation {
   155  		if node.Isolation != UnspecifiedIsolation {
   156  			return errIsolationLevelSpecifiedMultipleTimes
   157  		}
   158  		node.Isolation = other.Isolation
   159  	}
   160  	if other.UserPriority != UnspecifiedUserPriority {
   161  		if node.UserPriority != UnspecifiedUserPriority {
   162  			return errUserPrioritySpecifiedMultipleTimes
   163  		}
   164  		node.UserPriority = other.UserPriority
   165  	}
   166  	if other.AsOf.Expr != nil {
   167  		if node.AsOf.Expr != nil {
   168  			return errAsOfSpecifiedMultipleTimes
   169  		}
   170  		node.AsOf.Expr = other.AsOf.Expr
   171  	}
   172  	if other.ReadWriteMode != UnspecifiedReadWriteMode {
   173  		if node.ReadWriteMode != UnspecifiedReadWriteMode {
   174  			return errReadModeSpecifiedMultipleTimes
   175  		}
   176  		node.ReadWriteMode = other.ReadWriteMode
   177  	}
   178  	if node.ReadWriteMode != UnspecifiedReadWriteMode &&
   179  		node.ReadWriteMode != ReadOnly &&
   180  		node.AsOf.Expr != nil {
   181  		return ErrAsOfSpecifiedWithReadWrite
   182  	}
   183  	return nil
   184  }
   185  
   186  // BeginTransaction represents a BEGIN statement
   187  type BeginTransaction struct {
   188  	Modes TransactionModes
   189  }
   190  
   191  // Format implements the NodeFormatter interface.
   192  func (node *BeginTransaction) Format(ctx *FmtCtx) {
   193  	ctx.WriteString("BEGIN TRANSACTION")
   194  	node.Modes.Format(ctx)
   195  }
   196  
   197  // CommitTransaction represents a COMMIT statement.
   198  type CommitTransaction struct{}
   199  
   200  // Format implements the NodeFormatter interface.
   201  func (node *CommitTransaction) Format(ctx *FmtCtx) {
   202  	ctx.WriteString("COMMIT TRANSACTION")
   203  }
   204  
   205  // RollbackTransaction represents a ROLLBACK statement.
   206  type RollbackTransaction struct{}
   207  
   208  // Format implements the NodeFormatter interface.
   209  func (node *RollbackTransaction) Format(ctx *FmtCtx) {
   210  	ctx.WriteString("ROLLBACK TRANSACTION")
   211  }
   212  
   213  // Savepoint represents a SAVEPOINT <name> statement.
   214  type Savepoint struct {
   215  	Name Name
   216  }
   217  
   218  // Format implements the NodeFormatter interface.
   219  func (node *Savepoint) Format(ctx *FmtCtx) {
   220  	ctx.WriteString("SAVEPOINT ")
   221  	node.Name.Format(ctx)
   222  }
   223  
   224  // ReleaseSavepoint represents a RELEASE SAVEPOINT <name> statement.
   225  type ReleaseSavepoint struct {
   226  	Savepoint Name
   227  }
   228  
   229  // Format implements the NodeFormatter interface.
   230  func (node *ReleaseSavepoint) Format(ctx *FmtCtx) {
   231  	ctx.WriteString("RELEASE SAVEPOINT ")
   232  	node.Savepoint.Format(ctx)
   233  }
   234  
   235  // RollbackToSavepoint represents a ROLLBACK TO SAVEPOINT <name> statement.
   236  type RollbackToSavepoint struct {
   237  	Savepoint Name
   238  }
   239  
   240  // Format implements the NodeFormatter interface.
   241  func (node *RollbackToSavepoint) Format(ctx *FmtCtx) {
   242  	ctx.WriteString("ROLLBACK TRANSACTION TO SAVEPOINT ")
   243  	node.Savepoint.Format(ctx)
   244  }