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

     1  // Copyright 2021 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 "strconv"
    14  
    15  // DeclareCursor represents a DECLARE statement.
    16  type DeclareCursor struct {
    17  	Name        Name
    18  	Select      *Select
    19  	Binary      bool
    20  	Scroll      CursorScrollOption
    21  	Sensitivity CursorSensitivity
    22  	Hold        bool
    23  }
    24  
    25  // Format implements the NodeFormatter interface.
    26  func (node *DeclareCursor) Format(ctx *FmtCtx) {
    27  	ctx.WriteString("DECLARE ")
    28  	ctx.FormatNode(&node.Name)
    29  	ctx.WriteString(" ")
    30  	if node.Binary {
    31  		ctx.WriteString("BINARY ")
    32  	}
    33  	if node.Sensitivity != UnspecifiedSensitivity {
    34  		ctx.WriteString(node.Sensitivity.String())
    35  		ctx.WriteString(" ")
    36  	}
    37  	if node.Scroll != UnspecifiedScroll {
    38  		ctx.WriteString(node.Scroll.String())
    39  		ctx.WriteString(" ")
    40  	}
    41  	ctx.WriteString("CURSOR ")
    42  	if node.Hold {
    43  		ctx.WriteString("WITH HOLD ")
    44  	}
    45  	ctx.WriteString("FOR ")
    46  	ctx.FormatNode(node.Select)
    47  }
    48  
    49  // CursorScrollOption represents the scroll option, if one was given, for a
    50  // DECLARE statement.
    51  type CursorScrollOption int8
    52  
    53  const (
    54  	// UnspecifiedScroll represents no SCROLL option having been given. In
    55  	// Postgres, this is like NO SCROLL, but the returned cursor also supports
    56  	// some simple cases of backward seeking. For CockroachDB, this is the same
    57  	// as NO SCROLL.
    58  	UnspecifiedScroll CursorScrollOption = iota
    59  	// Scroll represents the SCROLL option. It is supposed to indicate that the
    60  	// declared cursor is "scrollable", meaning it can be seeked backward.
    61  	Scroll
    62  	// NoScroll represents the NO SCROLL option, which means that the declared
    63  	// cursor can only be moved forward.
    64  	NoScroll
    65  )
    66  
    67  func (o CursorScrollOption) String() string {
    68  	switch o {
    69  	case Scroll:
    70  		return "SCROLL"
    71  	case NoScroll:
    72  		return "NO SCROLL"
    73  	}
    74  	return ""
    75  }
    76  
    77  // CursorSensitivity represents the "sensitivity" of a cursor, which describes
    78  // whether it sees writes that occur within the transaction after it was
    79  // declared.
    80  // CockroachDB, like Postgres, only supports "insensitive" cursors, and all
    81  // three variants of sensitivity here resolve to insensitive. SENSITIVE cursors
    82  // are not supported.
    83  type CursorSensitivity int
    84  
    85  const (
    86  	// UnspecifiedSensitivity indicates that no sensitivity was specified. This
    87  	// is the same as INSENSITIVE.
    88  	UnspecifiedSensitivity CursorSensitivity = iota
    89  	// Insensitive indicates that the cursor is "insensitive" to subsequent
    90  	// writes, meaning that it sees a snapshot of data from the moment it was
    91  	// declared, and won't see subsequent writes within the transaction.
    92  	Insensitive
    93  	// Asensitive indicates that "the cursor is implementation dependent".
    94  	Asensitive
    95  )
    96  
    97  func (o CursorSensitivity) String() string {
    98  	switch o {
    99  	case Insensitive:
   100  		return "INSENSITIVE"
   101  	case Asensitive:
   102  		return "ASENSITIVE"
   103  	}
   104  	return ""
   105  }
   106  
   107  // CursorStmt represents the shared structure between a FETCH and MOVE statement.
   108  type CursorStmt struct {
   109  	Name      Name
   110  	FetchType FetchType
   111  	Count     int64
   112  }
   113  
   114  // FetchCursor represents a FETCH statement.
   115  type FetchCursor struct {
   116  	CursorStmt
   117  }
   118  
   119  // MoveCursor represents a MOVE statement.
   120  type MoveCursor struct {
   121  	CursorStmt
   122  }
   123  
   124  // FetchType represents the type of a FETCH (or MOVE) statement.
   125  type FetchType int
   126  
   127  const (
   128  	// FetchNormal represents a FETCH statement that doesn't have a special
   129  	// qualifier. It's used for FORWARD, BACKWARD, NEXT, and PRIOR.
   130  	FetchNormal FetchType = iota
   131  	// FetchRelative represents a FETCH RELATIVE statement.
   132  	FetchRelative
   133  	// FetchAbsolute represents a FETCH ABSOLUTE statement.
   134  	FetchAbsolute
   135  	// FetchFirst represents a FETCH FIRST statement.
   136  	FetchFirst
   137  	// FetchLast represents a FETCH LAST statement.
   138  	FetchLast
   139  	// FetchAll represents a FETCH ALL statement.
   140  	FetchAll
   141  	// FetchBackwardAll represents a FETCH BACKWARD ALL statement.
   142  	FetchBackwardAll
   143  )
   144  
   145  func (o FetchType) String() string {
   146  	switch o {
   147  	case FetchNormal:
   148  		return ""
   149  	case FetchRelative:
   150  		return "RELATIVE"
   151  	case FetchAbsolute:
   152  		return "ABSOLUTE"
   153  	case FetchFirst:
   154  		return "FIRST"
   155  	case FetchLast:
   156  		return "LAST"
   157  	case FetchAll:
   158  		return "ALL"
   159  	case FetchBackwardAll:
   160  		return "BACKWARD ALL"
   161  	}
   162  	return ""
   163  }
   164  
   165  // HasCount returns true if the given fetch type should be printed with an
   166  // associated count.
   167  func (o FetchType) HasCount() bool {
   168  	switch o {
   169  	case FetchNormal, FetchRelative, FetchAbsolute:
   170  		return true
   171  	}
   172  	return false
   173  }
   174  
   175  // Format implements the NodeFormatter interface.
   176  func (c CursorStmt) Format(ctx *FmtCtx) {
   177  	fetchType := c.FetchType.String()
   178  	if fetchType != "" {
   179  		ctx.WriteString(fetchType)
   180  		ctx.WriteString(" ")
   181  	}
   182  	if c.FetchType.HasCount() {
   183  		if ctx.HasFlags(FmtHideConstants) {
   184  			ctx.WriteByte('0')
   185  		} else {
   186  			ctx.WriteString(strconv.Itoa(int(c.Count)))
   187  		}
   188  		ctx.WriteString(" ")
   189  	}
   190  	ctx.FormatNode(&c.Name)
   191  }
   192  
   193  // Format implements the NodeFormatter interface.
   194  func (f FetchCursor) Format(ctx *FmtCtx) {
   195  	ctx.WriteString("FETCH ")
   196  	f.CursorStmt.Format(ctx)
   197  }
   198  
   199  // Format implements the NodeFormatter interface.
   200  func (m MoveCursor) Format(ctx *FmtCtx) {
   201  	ctx.WriteString("MOVE ")
   202  	m.CursorStmt.Format(ctx)
   203  }
   204  
   205  // CloseCursor represents a CLOSE statement.
   206  type CloseCursor struct {
   207  	Name Name
   208  	All  bool
   209  }
   210  
   211  // Format implements the NodeFormatter interface.
   212  func (c CloseCursor) Format(ctx *FmtCtx) {
   213  	ctx.WriteString("CLOSE ")
   214  	if c.All {
   215  		ctx.WriteString("ALL")
   216  	} else {
   217  		ctx.FormatNode(&c.Name)
   218  	}
   219  }