Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plpgsql: tracking issue for 23.2 PLpgSQL features #105254

Closed
9 tasks done
DrewKimball opened this issue Jun 21, 2023 · 1 comment
Closed
9 tasks done

plpgsql: tracking issue for 23.2 PLpgSQL features #105254

DrewKimball opened this issue Jun 21, 2023 · 1 comment
Assignees
Labels
C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) T-sql-queries SQL Queries Team
Projects

Comments

@DrewKimball
Copy link
Collaborator

DrewKimball commented Jun 21, 2023

This is a tracking issue for PLpgSQL features that are planned for 23.2.

Epic: CRDB-799

Jira issue: CRDB-28943

@DrewKimball DrewKimball added the C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) label Jun 21, 2023
@DrewKimball DrewKimball added this to Triage in SQL Queries via automation Jun 21, 2023
@blathers-crl blathers-crl bot added the T-sql-queries SQL Queries Team label Jun 21, 2023
@DrewKimball DrewKimball self-assigned this Jun 21, 2023
@DrewKimball DrewKimball moved this from Triage to Active in SQL Queries Jun 21, 2023
@exalate-issue-sync exalate-issue-sync bot added T-sql-queries SQL Queries Team and removed T-sql-queries SQL Queries Team labels Jun 21, 2023
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Jul 12, 2023
This patch implements tail-call optimization for the nested routine
execution that is used to handle PLpgSQL control flow. PLpgSQL sub-routines
are always tail calls because they are built as "continuation" functions,
so we can always use the optimization for PLpgSQL. Tail-call optimization
is only possible if the plan is not distributed (although we may not
currently distribute such plans anyway).

The optimization is performed by setting a `deferredRoutineReceiver`
field on the planner before planning and running a nested routine.
This `deferredRoutineReceiver` allows a routine in tail-call
position to send the information needed to evaluate itself to its
parent, and then return NULL. Once the parent routine receives the
result, it checks whether `deferredRoutineReceiver` received a
deferred nested routine, and if so, evaluates it to obtain the
actual result.

Given a simple looping function like the following:
```
CREATE FUNCTION f(n INT) RETURNS INT AS $$
  DECLARE
    i INT := 0;
  BEGIN
    LOOP
      IF i >= n THEN
        EXIT;
      END IF;
      i := i + 1;
    END LOOP;
    RETURN i;
  END
$$ LANGUAGE PLpgSQL;
```
This optimization takes runtime on my machine for `n=100000` from >20m
to ~2s.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Jul 20, 2023
This patch implements tail-call optimization for the nested routine
execution that is used to handle PLpgSQL control flow. PLpgSQL sub-routines
are always tail calls because they are built as "continuation" functions,
so we can always use the optimization for PLpgSQL. Tail-call optimization
is only possible if the plan is not distributed (although we may not
currently distribute such plans anyway).

The optimization is performed by setting a `deferredRoutineReceiver`
field on the planner before planning and running a nested routine.
This `deferredRoutineReceiver` allows a routine in tail-call
position to send the information needed to evaluate itself to its
parent, and then return NULL. Once the parent routine receives the
result, it checks whether `deferredRoutineReceiver` received a
deferred nested routine, and if so, evaluates it to obtain the
actual result.

Given a simple looping function like the following:
```
CREATE FUNCTION f(n INT) RETURNS INT AS $$
  DECLARE
    i INT := 0;
  BEGIN
    LOOP
      IF i >= n THEN
        EXIT;
      END IF;
      i := i + 1;
    END LOOP;
    RETURN i;
  END
$$ LANGUAGE PLpgSQL;
```
This optimization takes runtime on my machine for `n=100000` from >20m
to ~2s.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Jul 20, 2023
This patch implements tail-call optimization for the nested routine
execution that is used to handle PLpgSQL control flow. PLpgSQL sub-routines
are always tail calls because they are built as "continuation" functions,
so we can always use the optimization for PLpgSQL. Tail-call optimization
is only possible if the plan is not distributed (although we may not
currently distribute such plans anyway).

The optimization is performed by setting a `deferredRoutineReceiver`
field on the planner before planning and running a nested routine.
This `deferredRoutineReceiver` allows a routine in tail-call
position to send the information needed to evaluate itself to its
parent, and then return NULL. Once the parent routine receives the
result, it checks whether `deferredRoutineReceiver` received a
deferred nested routine, and if so, evaluates it to obtain the
actual result.

Given a simple looping function like the following:
```
CREATE FUNCTION f(n INT) RETURNS INT AS $$
  DECLARE
    i INT := 0;
  BEGIN
    LOOP
      IF i >= n THEN
        EXIT;
      END IF;
      i := i + 1;
    END LOOP;
    RETURN i;
  END
$$ LANGUAGE PLpgSQL;
```
This optimization takes runtime on my machine for `n=100000` from >20m
to ~2s.

Informs cockroachdb#105254

Release note: None
craig bot pushed a commit that referenced this issue Jul 21, 2023
106668: plpgsql: implement tail-call optimization for PLpgSQL routines r=DrewKimball a=DrewKimball

This patch implements tail-call optimization for the nested routine execution that is used to handle PLpgSQL control flow. PLpgSQL sub-routines are always tail calls because they are built as "continuation" functions, so we can always use the optimization for PLpgSQL. Tail-call optimization is only possible if the plan is not distributed (although we may not currently distribute such plans anyway).

The optimization is performed by setting a `deferredRoutineReceiver` field on the planner before planning and running a nested routine. This `deferredRoutineReceiver` allows a routine in tail-call position to send the information needed to evaluate itself to its parent, and then return NULL. Once the parent routine receives the result, it checks whether `deferredRoutineReceiver` received a deferred nested routine, and if so, evaluates it to obtain the actual result.

Given a simple looping function like the following:
```
CREATE FUNCTION f(n INT) RETURNS INT AS $$
  DECLARE
    i INT := 0;
  BEGIN
    LOOP
      IF i >= n THEN
        EXIT;
      END IF;
      i := i + 1;
    END LOOP;
    RETURN i;
  END
$$ LANGUAGE PLpgSQL;
```
This optimization takes runtime on my machine for `n=100000` from >20m to ~2s.

Informs #105254

Release note: None

107205: cloud: allow parallel running of cloud unit tests r=rhu713 a=rhu713

Append a random uint64 in the paths of cloud unit tests to prevent parallel executions from interfering with each other. This is necessary since these tests now run for all release branches and can run in parallel.

Fixes: #107137
Fixes: #107139

Release note: None

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
Co-authored-by: Rui Hu <rui@cockroachlabs.com>
@DrewKimball DrewKimball self-assigned this Jul 21, 2023
THardy98 pushed a commit to THardy98/cockroach that referenced this issue Jul 24, 2023
This patch implements tail-call optimization for the nested routine
execution that is used to handle PLpgSQL control flow. PLpgSQL sub-routines
are always tail calls because they are built as "continuation" functions,
so we can always use the optimization for PLpgSQL. Tail-call optimization
is only possible if the plan is not distributed (although we may not
currently distribute such plans anyway).

The optimization is performed by setting a `deferredRoutineReceiver`
field on the planner before planning and running a nested routine.
This `deferredRoutineReceiver` allows a routine in tail-call
position to send the information needed to evaluate itself to its
parent, and then return NULL. Once the parent routine receives the
result, it checks whether `deferredRoutineReceiver` received a
deferred nested routine, and if so, evaluates it to obtain the
actual result.

Given a simple looping function like the following:
```
CREATE FUNCTION f(n INT) RETURNS INT AS $$
  DECLARE
    i INT := 0;
  BEGIN
    LOOP
      IF i >= n THEN
        EXIT;
      END IF;
      i := i + 1;
    END LOOP;
    RETURN i;
  END
$$ LANGUAGE PLpgSQL;
```
This optimization takes runtime on my machine for `n=100000` from >20m
to ~2s.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Aug 4, 2023
This patch adds support for executing PLpgSQL `IF` statements with
`ELSIF` branches (else if). `IF` statements were already executed as
CASE statements under the hood, so this change only requires building
the `ELSIF` branches and appending them to the `whens` list.

Informs cockroachdb#105254

Release note (sql change): Added support for specifying PLpgSQL `IF`
statements with `ELSIF` branches.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Aug 4, 2023
This patch fixes two behaviors related to RAISE statements handling
NULL values:
1. When a NULL value is passed as a formatting argument, it is printed
   as `<NULL>` in the result string.
2. When a NULL value is passed as a RAISE option (message, detail, etc.)
   a runtime `RAISE statement option cannot be null` error results.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Aug 4, 2023
This patch adds support for executing PLpgSQL `IF` statements with
`ELSIF` branches (else if). `IF` statements were already executed as
CASE statements under the hood, so this change only requires building
the `ELSIF` branches and appending them to the `whens` list.

Informs cockroachdb#105254

Release note (sql change): Added support for specifying PLpgSQL `IF`
statements with `ELSIF` branches.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Aug 4, 2023
This patch fixes two behaviors related to RAISE statements handling
NULL values:
1. When a NULL value is passed as a formatting argument, it is printed
   as `<NULL>` in the result string.
2. When a NULL value is passed as a RAISE option (message, detail, etc.)
   a runtime `RAISE statement option cannot be null` error results.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Aug 8, 2023
This patch adds support for executing PLpgSQL `IF` statements with
`ELSIF` branches (else if). `IF` statements were already executed as
CASE statements under the hood, so this change only requires building
the `ELSIF` branches and appending them to the `whens` list.

Informs cockroachdb#105254

Release note (sql change): Added support for specifying PLpgSQL `IF`
statements with `ELSIF` branches.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Sep 28, 2023
This patch adds support in the PLpgSQL parser for the following commands
related to cursors: `DECLARE`, `OPEN`, `FETCH`, `MOVE`, and `CLOSE`.
The `OPEN ... FOR EXECUTE ...` syntax is not currently implemented.

Informs cockroachdb#105254

Release note: None
craig bot pushed a commit that referenced this issue Sep 28, 2023
110709: plpgsql: implement OPEN statements r=DrewKimball a=DrewKimball

#### plpgsql: add parser support for cursors

This patch adds support in the PLpgSQL parser for the following commands
related to cursors: `DECLARE`, `OPEN`, `FETCH`, `MOVE`, and `CLOSE`.
The `OPEN ... FOR EXECUTE ...` syntax is not currently implemented.

Informs #105254

Release note: None

#### plpgsql: add execution support for OPEN statements

This patch adds support for executing PLpgSQL OPEN statements, which
open a SQL cursor in the current transaction. The name of the cursor
is supplied through a PLpgSQL variable. Since the `REFCURSOR` type
hasn't been implemented yet, this patch uses `STRING` in the
meantime.

Limitations that will be lifted in future PRs:
1. Unnamed cursor declarations are not supported. If a cursor is opened
   with no name supplied, a name should be automatically generated.
2. Bound cursors are not yet supported. It should be possible to declare
   a cursor in the `DECLARE` block with the query already defined, at
   which point it can be opened with `OPEN <cursor>;`.
3. A cursor cannot be opened in a routine with an exception block. This
   is because correct handling of this case is waiting on separate work
   to implement rollback of changes to database state on exceptions.

Informs #109709

Release note (sql change): Added initial support for executing the
PLpgSQL `OPEN` statement, which allows a PLpgSQL routine to create a
cursor. Currently, opening bound or unnamed cursors is not supported.
In addition, `OPEN` statements cannot be used in a routine with an
exception block.

111388: kvserver: latching changes for replicated shared locks r=nvanbenschoten a=arulajmani

Two locking requests from the same transaction that are trying to acquire replicated shared locks need to be isolated from one another. They don't need to be isolated against shared locking requests from other transactions and unreplicated shared lock attempts from the same transaction.

To achieve these semantics, we introduce a per-transaction range local key that all replicated shared locking requests declare non-MVCC write latches over.

Closes #109668

Release note: None

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
Co-authored-by: Arul Ajmani <arulajmani@gmail.com>
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Sep 29, 2023
This patch adds support for declaring and opening a _bound_ cursor.
Bound cursors allow a query to be associated with the cursor when it
is declared in a PLpgSQL `DECLARE` section. The cursor can then be
opened at any point in the main body of the PLpgSQL routine with
syntax like the following:
```
OPEN curs;
```
Note how there is no query supplied to this `OPEN` statement, unlike
for unbound cursors.

Informs cockroachdb#105254

Release note (sql change): Added support for declaring bound cursors,
which associate a query with a cursor in a PLpgSQL routine before it
is opened.
craig bot pushed a commit that referenced this issue Sep 29, 2023
111092: plpgsql: add support for bound cursor declarations r=DrewKimball a=DrewKimball

#### plpgsql: add support for bound cursor declarations

This patch adds support for declaring and opening a _bound_ cursor.
Bound cursors allow a query to be associated with the cursor when it
is declared in a PLpgSQL `DECLARE` section. The cursor can then be
opened at any point in the main body of the PLpgSQL routine with
syntax like the following:
```
OPEN curs;
```
Note how there is no query supplied to this `OPEN` statement, unlike
for unbound cursors.

Informs #105254

Release note (sql change): Added support for declaring bound cursors,
which associate a query with a cursor in a PLpgSQL routine before it
is opened.

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
THardy98 pushed a commit to THardy98/cockroach that referenced this issue Oct 6, 2023
This patch adds support in the PLpgSQL parser for the following commands
related to cursors: `DECLARE`, `OPEN`, `FETCH`, `MOVE`, and `CLOSE`.
The `OPEN ... FOR EXECUTE ...` syntax is not currently implemented.

Informs cockroachdb#105254

Release note: None
THardy98 pushed a commit to THardy98/cockroach that referenced this issue Oct 6, 2023
This patch adds support for declaring and opening a _bound_ cursor.
Bound cursors allow a query to be associated with the cursor when it
is declared in a PLpgSQL `DECLARE` section. The cursor can then be
opened at any point in the main body of the PLpgSQL routine with
syntax like the following:
```
OPEN curs;
```
Note how there is no query supplied to this `OPEN` statement, unlike
for unbound cursors.

Informs cockroachdb#105254

Release note (sql change): Added support for declaring bound cursors,
which associate a query with a cursor in a PLpgSQL routine before it
is opened.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Oct 7, 2023
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Oct 9, 2023
craig bot pushed a commit that referenced this issue Oct 9, 2023
111970: plpgsql,clusterversion: add a version gate for PLpgSQL routines r=DrewKimball a=DrewKimball

Informs #105254

Release note: None

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
aliher1911 pushed a commit to aliher1911/cockroach that referenced this issue Oct 9, 2023
This patch adds support in the PLpgSQL parser for the following commands
related to cursors: `DECLARE`, `OPEN`, `FETCH`, `MOVE`, and `CLOSE`.
The `OPEN ... FOR EXECUTE ...` syntax is not currently implemented.

Informs cockroachdb#105254

Release note: None
aliher1911 pushed a commit to aliher1911/cockroach that referenced this issue Oct 9, 2023
This patch adds support for declaring and opening a _bound_ cursor.
Bound cursors allow a query to be associated with the cursor when it
is declared in a PLpgSQL `DECLARE` section. The cursor can then be
opened at any point in the main body of the PLpgSQL routine with
syntax like the following:
```
OPEN curs;
```
Note how there is no query supplied to this `OPEN` statement, unlike
for unbound cursors.

Informs cockroachdb#105254

Release note (sql change): Added support for declaring bound cursors,
which associate a query with a cursor in a PLpgSQL routine before it
is opened.
@DrewKimball
Copy link
Collaborator Author

Note: FOR loops and OTHERS branch were dropped for 23.2.

DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Oct 11, 2023
This patch ensures that PLpgSQL parsing errors are correctly propagated
in all cases. Previously, there were a few cases (like variable declaration
type parsing) where an error didn't halt parsing. The contract for
`GetTypeFromValidSQLSyntax` is also clarified, since it is ok to call with
an invalid type name as long as the error is properly handled.

Informs cockroachdb#105254

Release note: None
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Oct 16, 2023
This patch ensures that PLpgSQL parsing errors are correctly propagated
in all cases. Previously, there were a few cases (like variable declaration
type parsing) where an error didn't halt parsing. The contract for
`GetTypeFromValidSQLSyntax` is also clarified, since it is ok to call with
an invalid type name as long as the error is properly handled.

Informs cockroachdb#105254

Release note: None
craig bot pushed a commit that referenced this issue Oct 17, 2023
112200: plpgsql: correctly handle parsing errors r=DrewKimball a=DrewKimball

#### plpgsql: correctly handle parsing errors

This patch ensures that PLpgSQL parsing errors are correctly propagated
in all cases. Previously, there were a few cases (like variable declaration
type parsing) where an error didn't halt parsing. The contract for
`GetTypeFromValidSQLSyntax` is also clarified, since it is ok to call with
an invalid type name as long as the error is properly handled.

Informs #105254

Release note: None

#### plpgsql: handle multiple expressions when one expression is expected

Previously, the PLpgSQL parser could panic when the user supplied more
than one expression in a location where only one was expected, for example,
in a return statement. This was because the PLpgSQL parser delegated to
the SQL parser's `ParseExpr` function, which expects exactly one input
expression. This commit returns a syntax error instead of the panic by
switching to use `ParseExprs`, which can handle multiple input expressions.

Informs #109342

Release note: None

#### plpgsql: return correct error for invalid parantheses and missing expression

This patch fixes error messages in the PLpgSQL parser for the case when
the parenthesis nesting is invalid, and for the case when no expression
(or statement) is supplied. Previously, invalid parentheses would cause
a panic without an error code, and a missing expression had the incorrect
message, since it wasn't checked until the SQL parser attempted to read
an empty string. Now, both cases are checked immediately by the PLpgSQL
parser and the correct error is propagated.

Fixes #109342

Release note: None

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
blathers-crl bot pushed a commit that referenced this issue Oct 17, 2023
This patch ensures that PLpgSQL parsing errors are correctly propagated
in all cases. Previously, there were a few cases (like variable declaration
type parsing) where an error didn't halt parsing. The contract for
`GetTypeFromValidSQLSyntax` is also clarified, since it is ok to call with
an invalid type name as long as the error is properly handled.

Informs #105254

Release note: None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) T-sql-queries SQL Queries Team
Projects
Archived in project
Development

No branches or pull requests

1 participant