Skip to content

Commit 8e7f6c5

Browse files
committed
Merge remote-tracking branch 'upstream' into vector-avg-sum-functions
2 parents 6f38545 + a157725 commit 8e7f6c5

File tree

5 files changed

+578
-10
lines changed

5 files changed

+578
-10
lines changed

docs/control-flow/close-stmt.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
---
2+
layout: global
3+
title: CLOSE statement
4+
displayTitle: CLOSE statement
5+
license: |
6+
Licensed to the Apache Software Foundation (ASF) under one or more
7+
contributor license agreements. See the NOTICE file distributed with
8+
this work for additional information regarding copyright ownership.
9+
The ASF licenses this file to You under the Apache License, Version 2.0
10+
(the "License"); you may not use this file except in compliance with
11+
the License. You may obtain a copy of the License at
12+
13+
http://www.apache.org/licenses/LICENSE-2.0
14+
15+
Unless required by applicable law or agreed to in writing, software
16+
distributed under the License is distributed on an "AS IS" BASIS,
17+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
See the License for the specific language governing permissions and
19+
limitations under the License.
20+
---
21+
22+
Closes an open cursor and releases its resources.
23+
24+
The `CLOSE` statement closes a cursor that was previously opened with `OPEN`, freeing the memory and resources associated with its result set. After closing, the cursor can be reopened with `OPEN` to execute the query again with fresh parameter bindings.
25+
26+
## Syntax
27+
28+
```
29+
CLOSE cursor_name
30+
```
31+
32+
## Parameters
33+
34+
- **`cursor_name`**
35+
36+
The name of an open cursor. The cursor can be optionally qualified with a compound statement label (e.g., `outer_label.my_cursor`).
37+
38+
## Examples
39+
40+
```SQL
41+
-- Basic cursor lifecycle
42+
> BEGIN
43+
DECLARE x INT;
44+
DECLARE my_cursor CURSOR FOR SELECT id FROM range(3);
45+
46+
OPEN my_cursor;
47+
FETCH my_cursor INTO x;
48+
VALUES (x);
49+
CLOSE my_cursor;
50+
END;
51+
0
52+
53+
-- Close cursor in handler
54+
> BEGIN
55+
DECLARE x INT;
56+
DECLARE my_cursor CURSOR FOR SELECT id FROM range(2);
57+
58+
DECLARE EXIT HANDLER FOR NOT FOUND
59+
BEGIN
60+
CLOSE my_cursor;
61+
VALUES ('Cursor closed on completion');
62+
END;
63+
64+
OPEN my_cursor;
65+
REPEAT
66+
FETCH my_cursor INTO x;
67+
UNTIL false END REPEAT;
68+
END;
69+
Cursor closed on completion
70+
71+
-- Reopen cursor with different parameters
72+
> BEGIN
73+
DECLARE x INT;
74+
DECLARE param_cursor CURSOR FOR SELECT id FROM range(10) WHERE id = ?;
75+
76+
OPEN param_cursor USING 3;
77+
FETCH param_cursor INTO x;
78+
VALUES ('First open:', x);
79+
CLOSE param_cursor;
80+
81+
OPEN param_cursor USING 7;
82+
FETCH param_cursor INTO x;
83+
VALUES ('Second open:', x);
84+
CLOSE param_cursor;
85+
END;
86+
First open:|3
87+
Second open:|7
88+
89+
-- Qualified cursor name with label
90+
> BEGIN
91+
outer_lbl: BEGIN
92+
DECLARE outer_cur CURSOR FOR SELECT id FROM range(3);
93+
DECLARE x INT;
94+
95+
OPEN outer_cur;
96+
FETCH outer_cur INTO x;
97+
98+
inner_lbl: BEGIN
99+
FETCH outer_lbl.outer_cur INTO x;
100+
END;
101+
102+
CLOSE outer_lbl.outer_cur;
103+
VALUES ('Closed from outer scope');
104+
END;
105+
END;
106+
Closed from outer scope
107+
108+
-- Processing all rows before close
109+
> BEGIN
110+
DECLARE x INT;
111+
DECLARE done BOOLEAN DEFAULT false;
112+
DECLARE results STRING DEFAULT '';
113+
DECLARE my_cursor CURSOR FOR SELECT id FROM range(5);
114+
115+
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
116+
117+
OPEN my_cursor;
118+
REPEAT
119+
FETCH my_cursor INTO x;
120+
IF NOT done THEN
121+
SET results = results || CAST(x AS STRING) || ',';
122+
END IF;
123+
UNTIL done END REPEAT;
124+
CLOSE my_cursor;
125+
126+
VALUES (results);
127+
END;
128+
0,1,2,3,4,
129+
```
130+
131+
## Notes
132+
133+
- The cursor must be open before calling `CLOSE`. Attempting to close a cursor that is not open raises a `CURSOR_NOT_OPEN` error.
134+
- After closing, the cursor can be reopened with `OPEN`. This is useful when you want to re-execute the cursor's query with different parameter bindings.
135+
- Cursors are automatically closed in the following scenarios:
136+
- When the compound statement that declares them exits normally
137+
- When an `EXIT` handler is triggered (all cursors in the compound statement and nested compounds are closed)
138+
- When the compound statement exits due to an unhandled exception
139+
- It is good practice to explicitly close cursors when they are no longer needed, rather than relying on implicit closure. This frees resources earlier and makes the code's intent clearer.
140+
- Closing a cursor does not affect the cursor declaration. The cursor name remains in scope and can be reopened.
141+
142+
## Related articles
143+
144+
- [Compound Statement](../control-flow/compound-stmt.html)
145+
- [OPEN Statement](../control-flow/open-stmt.html)
146+
- [FETCH Statement](../control-flow/fetch-stmt.html)
147+
- [SQL Scripting](../sql-ref-scripting.html)

docs/control-flow/compound-stmt.md

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Implements a SQL Script block that can contain a sequence of SQL statements, con
2727
[ label : ]
2828
BEGIN
2929
[ { declare_variable | declare_condition } ; [...] ]
30+
[ declare_cursor ; [...] ]
3031
[ declare_handler ; [...] ]
3132
[ SQL_statement ; [...] ]
3233
END [ label ]
@@ -37,11 +38,15 @@ declare_variable
3738
declare_condition
3839
DECLARE condition_name CONDITION [ FOR SQLSTATE [ VALUE ] sqlstate ]
3940
41+
declare_cursor
42+
DECLARE cursor_name [ ASENSITIVE | INSENSITIVE ] CURSOR
43+
FOR query
44+
4045
declare_handler
4146
DECLARE handler_type HANDLER FOR condition_values handler_action
4247
4348
handler_type
44-
EXIT
49+
{ EXIT | CONTINUE }
4550
4651
condition_values
4752
{ { SQLSTATE [ VALUE ] sqlstate | condition_name } [, ...] |
@@ -89,7 +94,23 @@ condition_values
8994

9095
- **`sqlstate`**
9196

92-
A `STRING` literal of 5 alphanumeric characters (case insensitive) consisting of A-Z and 0..9. The SQLSTATE must not start with ‘00’, ‘01’, or ‘XX’. Any SQLSTATE starting with ‘02’ will be caught by the predefined NOT FOUND exception as well. If not specified, the SQLSTATE is ‘45000’.
97+
A `STRING` literal of 5 alphanumeric characters (case insensitive) consisting of A-Z and 0..9. The SQLSTATE must not start with `'00'`, `'01'`, or `'XX'`. Any SQLSTATE starting with `'02'` will be caught by the predefined `NOT FOUND` handler as well. If not specified, the SQLSTATE is `'45000'`.
98+
99+
- **`declare_cursor`**
100+
101+
A local cursor declaration for iterating through query results.
102+
103+
- **`cursor_name`**
104+
105+
An unqualified name for the cursor. The name must be unique among all cursors declared in this compound statement. Cursors can be qualified with the compound statement `label` to disambiguate duplicate names.
106+
107+
- **`ASENSITIVE`** or **`INSENSITIVE`**
108+
109+
Optional keywords specifying that once the cursor is opened, the result set is not affected by DML changes within or outside the session. This is the default and only supported behavior.
110+
111+
- **`query`**
112+
113+
The query that defines the cursor. The query is not executed until the cursor is opened with `OPEN cursor_name`. At open time, any variable references and parameter markers in the query are bound to their current values.
93114

94115
- **`declare_handler`**
95116

@@ -99,7 +120,11 @@ condition_values
99120

100121
- **`EXIT`**
101122

102-
Classifies the handler to exit the compound statement after the condition is handled.
123+
Classifies the handler to exit the compound statement after the condition is handled. All cursors opened within the compound statement and nested compound statements are implicitly closed.
124+
125+
- **`CONTINUE`**
126+
127+
Classifies the handler to continue execution after the handler completes. Execution resumes with the statement following the one that raised the condition.
103128

104129
- **`condition_values`**
105130

@@ -121,7 +146,7 @@ condition_values
121146

122147
- **`NOT FOUND`**
123148

124-
Applies to any error condition with a SQLSTATE ‘02’ class.
149+
Applies to any condition with a SQLSTATE `'02xxx'` class. This includes the `CURSOR_NO_MORE_ROWS` condition (SQLSTATE `'02000'`) raised when fetching beyond the end of a cursor's result set.
125150

126151
- **`handler_action`**
127152

@@ -136,7 +161,7 @@ condition_values
136161
## Examples
137162

138163
```SQL
139-
-- A compound statement with local variables, and exit hanlder and a nested compound.
164+
-- A compound statement with local variables, an exit handler and a nested compound.
140165
> BEGIN
141166
DECLARE a INT DEFAULT 1;
142167
DECLARE b INT DEFAULT 5;
@@ -149,11 +174,35 @@ condition_values
149174
VALUES (a);
150175
END;
151176
15
177+
178+
-- A compound statement with a cursor and a CONTINUE handler for iteration.
179+
> BEGIN
180+
DECLARE x INT;
181+
DECLARE done BOOLEAN DEFAULT false;
182+
DECLARE total INT DEFAULT 0;
183+
DECLARE my_cursor CURSOR FOR SELECT id FROM range(5);
184+
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
185+
186+
OPEN my_cursor;
187+
REPEAT
188+
FETCH my_cursor INTO x;
189+
IF NOT done THEN
190+
SET total = total + x;
191+
END IF;
192+
UNTIL done END REPEAT;
193+
CLOSE my_cursor;
194+
195+
VALUES (total);
196+
END;
197+
10
152198
```
153199

154200
## Related articles
155201

156202
- [SQL Scripting](../sql-ref-scripting.html)
203+
- [OPEN Statement](../control-flow/open-stmt.html)
204+
- [FETCH Statement](../control-flow/fetch-stmt.html)
205+
- [CLOSE Statement](../control-flow/close-stmt.html)
157206
- [CASE Statement](../control-flow/case-stmt.html)
158207
- [IF Statement](../control-flow/if-stmt.html)
159208
- [LOOP Statement](../control-flow/loop-stmt.html)

0 commit comments

Comments
 (0)