Skip to content

Commit

Permalink
Merge #111329
Browse files Browse the repository at this point in the history
111329: plpgsql: add support for unnamed cursors r=DrewKimball a=DrewKimball

#### plpgsql: add builtin to generate unique cursor names

This patch adds a builtin function `crdb_internal.plpgsql_gen_cursor_name`
that generates a unique name for a PLpgSQL cursor if the supplied name
is NULL. It then returns the resulting name to be used when opening
a cursor. This will be used in a following commit to implement unnamed
PLpgSQL cursors.

Informs #109709

Release note: None

#### plpgsql: add support for unnamed cursors

This patch adds support for opening an "unnamed" cursor in a PLpgSQL
routine. A PLpgSQL cursor is unnamed when the value for the cursor
variable is `NULL`. When an unnamed cursor is opened, a name will be
generated for it like `<unnamed portal 1>` that is guaranteed not to
conflict with an existing cursor or portal name. The PLpgSQL variable
that represents the cursor's name is updated to reflect the generated
name.

Informs #109709

Release note (sql change): Added support for unnamed PLpgSQL cursors,
which generate a unique name when no cursor name was specified.

Co-authored-by: Drew Kimball <[email protected]>
  • Loading branch information
craig[bot] and DrewKimball committed Oct 3, 2023
2 parents 4494e94 + d2d9656 commit ef2fd68
Show file tree
Hide file tree
Showing 18 changed files with 692 additions and 137 deletions.
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/3node-tenant/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/sql/faketreeeval/evalctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,11 @@ func (*DummyEvalPlanner) Optimizer() interface{} {
return nil
}

// GenUniqueCursorName is part of the eval.Planner interface.
func (*DummyEvalPlanner) GenUniqueCursorName() tree.Name {
return ""
}

var _ eval.Planner = &DummyEvalPlanner{}

var errEvalPlanner = pgerror.New(pgcode.ScalarOperationCannotRunWithoutFullSessionContext,
Expand Down
95 changes: 95 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/plpgsql_builtins
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Testing crdb_internal.plpgsql_gen_cursor_name.
query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 1>

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 2>

statement ok
BEGIN;
DECLARE "<unnamed portal 3>" CURSOR FOR SELECT 1;

query T
SELECT name FROM pg_cursors;
----
<unnamed portal 3>

# Skip manually generated duplicate names.
query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 4>

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 5>

statement ok
CLOSE "<unnamed portal 3>";

# Keep incrementing after a "gap" opens.
query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 6>

statement ok;
ABORT;

# Continue incrementing over transaction boundaries.
query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 7>

# If the name is already set, don't generate a new one.
query T
SELECT crdb_internal.plpgsql_gen_cursor_name('foo');
----
foo

query T
SELECT crdb_internal.plpgsql_gen_cursor_name('bar');
----
bar

query T
SELECT crdb_internal.plpgsql_gen_cursor_name('');
----
·

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 8>

# Starting a new session restarts the counter.
user testuser

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 1>

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 2>

# Returning to the old session continues the old counter.
user root

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 9>

query T
SELECT crdb_internal.plpgsql_gen_cursor_name(NULL);
----
<unnamed portal 10>
Loading

0 comments on commit ef2fd68

Please sign in to comment.