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 }